Dataclasses and property decorator

前端 未结 10 1672
没有蜡笔的小新
没有蜡笔的小新 2020-12-15 04:43

I\'ve been reading up on Python 3.7\'s dataclass as an alternative to namedtuples (what I typically use when having to group data in a structure). I was wondering if datacla

10条回答
  •  渐次进展
    2020-12-15 05:06

    Here's what I did to define the field as a property in __post_init__. This is a total hack, but it works with dataclasses dict-based initialization and even with marshmallow_dataclasses.

    from dataclasses import dataclass, field, asdict
    
    
    @dataclass
    class Test:
        name: str = "schbell"
        _name: str = field(init=False, repr=False)
    
        def __post_init__(self):
            # Just so that we don't create the property a second time.
            if not isinstance(getattr(Test, "name", False), property):
                self._name = self.name
                Test.name = property(Test._get_name, Test._set_name)
    
        def _get_name(self):
            return self._name
    
        def _set_name(self, val):
            self._name = val
    
    
    if __name__ == "__main__":
        t1 = Test()
        print(t1)
        print(t1.name)
        t1.name = "not-schbell"
        print(asdict(t1))
    
        t2 = Test("llebhcs")
        print(t2)
        print(t2.name)
        print(asdict(t2))
    

    This would print:

    Test(name='schbell')
    schbell
    {'name': 'not-schbell', '_name': 'not-schbell'}
    Test(name='llebhcs')
    llebhcs
    {'name': 'llebhcs', '_name': 'llebhcs'}
    

    I actually started off from this blog post mentioned somewhere in this SO, but ran into the issue that the dataclass field was being set to type property because the decorator is applied to the class. That is,

    @dataclass
    class Test:
        name: str = field(default='something')
        _name: str = field(init=False, repr=False)
    
        @property
        def name():
            return self._name
    
        @name.setter
        def name(self, val):
            self._name = val
    

    would make name to be of type property and not str. So, the setter will actually receive property object as the argument instead of the field default.

提交回复
热议问题