1

Trying my luck with inheritance with data classes (Python 3.9.13).

Given the following:

from dataclasses import dataclass
from datetime import datetime


@dataclass()
class BookMetadata():
    '''Parent class.'''
    
    isbn: str 
    title: str 
    author: str
    publisher: str
    date_published: int
    

    def __post_init__(self):
        '''Change attributes after assignment.'''
            
        # Change date from UNIX to YYYY-MM-DD HH:MM:SS
        self.date_published = datetime.fromtimestamp(int(str(self.date_published))).strftime('%Y-%m-%d %H:%M:%S')
      

@dataclass()
class RetailPrice(BookMetadata):
    '''Child class.'''
    
    def __init__(self, 
                 isbn, title, author, publisher, date_published,
                 price_usd, price_aud, price_eur, price_gbp) -> None:
        
        BookMetadata.__init__(isbn, title, author, publisher, date_published)
        
        self.price_usd: float = price_usd
        self.price_aud: float = price_aud
        self.price_eur: float = price_eur
        self.price_gbp: float = price_gbp


    def __post_init__(self):
        self.price_usd = str(self.price_usd)

and the values assigned as such:

book1 = RetailPrice(isbn='1234-5678-9000', 
                    title='My book', 
                    author='Name Surname', 
                    publisher='My publisher',
                    date_published=1670536799, 
                    price_usd=17.99, 
                    price_aud=23.99, 
                    price_eur=15.99, 
                    price_gbp=16.99)

I get a TypeError:: TypeError: __init__() missing 1 required positional argument: 'date_published', but this was provided in the assignment.

Is this due to the fact that the parent class has no __init__?

PS: this is my attempt at reproducing line 21 in the image below, having to work with data classes instead of regular classes: enter image description here

1 Answer 1

1

Since you are using a subclass of BookMetadata you can just initialise the superclass from child class using super() -


@dataclass()
class RetailPrice(BookMetadata):
    '''Child class.'''
    
    def __init__(self, 
                 isbn, title, author, publisher, date_published,
                 price_usd, price_aud, price_eur, price_gbp) -> None:
        super().__init__(isbn, title, author, publisher, date_published)
        self.price_usd: float = price_usd
        self.price_aud: float = price_aud
        self.price_eur: float = price_eur
        self.price_gbp: float = price_gbp

The reason for the error in your original code is because of the missing self argument to BookMetadata.__init__(), since you don't have an instance of BookMetadata class, so one argument was missing(self + 5 additional arguments, so it was giving error on the last missing argument date_published)

Sign up to request clarification or add additional context in comments.

8 Comments

Uhm, adding a __post_init__ method to the child class with exactly the same syntax as the parent class returns an AttributeError, despite that attribute being properly referenced in the code and assigned at runtime. I added def __post_init__(self): self.price_usd = str(self.price_usd), but at runtime I get AttributeError: 'RetailPrice' object has no attribute 'price_usd'
Can you share the corresponding code? Maybe, you are trying to access some non-existing attribute? You should be able to access the super class's attributes as self.isbn directly for example.
Yep, look at the edited code. I think the attribute is existing, but can there be confusion between the __post_init__ of the parent class and that of the child class?
Moving the super().__init__(isbn, title, author, publisher, date_published) part to below the dataclass arguments fixes the issue.
ahh ok, you would need to update the __repr__() method of the class, the parent class being a dataclass would have the function which would only print its own fields, while child one would print its own ones. So you might have to redefine it on your own to include all fields.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.