A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from http://mail.python.org/pipermail/python-dev/2018-February/152302.html below:

[Python-Dev] Should the dataclass frozen property apply to subclasses?

[Python-Dev] Should the dataclass frozen property apply to subclasses?Eric V. Smith eric at trueblade.com
Mon Feb 26 08:40:55 EST 2018
I've opened https://bugs.python.org/issue32953 to track this.

On 2/22/18 5:55 AM, Eric V. Smith wrote:
> On 2/22/2018 1:56 AM, Raymond Hettinger wrote:
>> When working on the docs for dataclasses, something unexpected came
>> up.  If a dataclass is specified to be frozen, that characteristic is
>> inherited by subclasses which prevents them from assigning additional
>> attributes:
>>
>>      >>> @dataclass(frozen=True)
>>      class D:
>>              x: int = 10
>>
>>      >>> class S(D):
>>              pass
>>
>>      >>> s = S()
>>      >>> s.cached = True
>>      Traceback (most recent call last):
>>        File "<pyshell#49>", line 1, in <module>
>>          s.cached = True
>>        File
>> "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/dataclasses.py",
>> line 448, in _frozen_setattr
>>          raise FrozenInstanceError(f'cannot assign to field {name!r}')
>>      dataclasses.FrozenInstanceError: cannot assign to field 'cached'
>
> This is because "frozen-ness" is implemented by adding __setattr__ and
> __delattr__ methods in D, which get inherited by S.
>

...

> A related issue is that dataclasses derived from frozen dataclasses are
> automatically "promoted" to being frozen.
>
>>>> @dataclass(frozen=True)
> ... class A:
> ...     i: int
> ...
>>>> @dataclass
> ... class B(A):
> ...     j: int
> ...
>>>> b = B(1, 2)
>>>> b.j = 3
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
>   File "C:\home\eric\local\python\cpython\lib\dataclasses.py", line 452,
> in _frozen_setattr
>     raise FrozenInstanceError(f'cannot assign to field {name!r}')
> dataclasses.FrozenInstanceError: cannot assign to field 'j'

This is tricky to fix.

Here's the problem with a inheriting a non-frozen dataclass from a 
frozen one. Consider class Y in this example:

@dataclass
class X:
     x: int

@dataclass
class Y(X):
     y: int

Y's __init__ looks like:

def __init__(self, x, y):
     self.x = x
     self.y = y

That is, all of the initializing for Y and its base classes which are 
dataclasses is done in Y's __init__. There are a number of reasons for 
this, including performance and not knowing how to call the base 
classes' __init__ methods.

If Y is frozen, then the __init__ currently looks like:

def __init__(self, x, y):
     object.__setattr__(self, 'x', x)
     object.__setattr__(self, 'y', y)

If X is frozen but Y isn't, then it should look like:

def __init__(self, x, y):
     object.__setattr__(self, 'x', x)
     self.y = y

But I currently can't generate the code that way, because I don't know 
if a base dataclass is frozen. That information is not saved on a dataclass.

I think the right thing to do is to record with each dataclass if it is 
frozen or not, so that derived classes can generate the correct code. 
Another option would be to always use object.__setattr__, but that will 
hurt performance in the common case.

As long as I'm saving if a dataclass is frozen, I should save all of the 
dataclass parameters on the class. Since it's per-class, it's not a lot 
of overhead.

I should probably separate the two issues here: 1) deriving a 
non-dataclass from a frozen dataclass and 2) deriving a non-frozen 
dataclass from a frozen dataclass, but since they're somewhat related 
I'm going to keep them together for the time being. #1 was Raymond's 
initial report.

Eric
More information about the Python-Dev mailing list

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4