Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dataclass: How do I create a field that does not need initializing which is automatically generated?

I used field(init= False) to disable initializing self.ref. It is then a value in post. The following code raises AttributeError: 'Data' object has no attribute 'ref'

from dataclasses import dataclass, field
def make_list(): return [[0] for k in range(9)]
@dataclass
class Data:
    rows: list
    cols: list
    blocks: list
    ref: dict = field(init=False)

    def __init__(self, slots=None):
        self.rows = make_list()
        self.cols = make_list()
        self.blocks = make_list()
        if slots:
            for i in range(9):
                for j in range(9):
                    self.cols[j][i] = self.rows[i][j] = slots[i][j]

    def __post_init__(self):  
          print("post-init executed")
        self.ref = {"rows": self.rows, "cols": self.cols, "blocks": self.blocks}
test = Data()
print(test)

I am using python 3.8. The code is tested in both pycharm/jupyter. (Same error)

Edit: after correcting the typo: __post__init__ to __post_init__ , I am still getting the error.

like image 321
theMobDog Avatar asked Nov 30 '25 11:11

theMobDog


1 Answers

Thanks to @wim and @juanpa.arrivillaga

Deleting the __init__ would fix the problem and let the __post_init__ run again. (As pointed out by wim and juanpa.arrivillaga) If I write my own __init__ , why even bother writing __post_init__ , I can write all post processing all I want in there. (line order)

from dataclasses import dataclass, field

@dataclass
class Data:
    rows: list
    cols: list = field(init=False) 
    blocks: list = field(init=False)
    ref: dict = field(init=False)

    def __post_init__(self): 
        print("post init\n\n")
        self.cols = [k*10 for k in self.rows]  # code transform rows to cols
        self.blocks = [k*20 for k in self.rows]  # code transform rows to blocks
        self.ref = {"rows": self.rows, "cols": self.cols, "blocks": self.blocks}

test = Data([1,2,3])
print(test)

Also, I might want to reconsider rewriting it using regular class as the code stands now since using dataclass here does not provide anything more than a regular class.

like image 103
theMobDog Avatar answered Dec 02 '25 04:12

theMobDog



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!