This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: InitVar should not be available on a @dataclass-decorated class
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.10, Python 3.9
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: eric.smith Nosy List: eric.smith, superbobry
Priority: normal Keywords:

Created on 2021-04-27 11:54 by superbobry, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (5)
msg392058 - (view) Author: Sergei Lebedev (superbobry) * Date: 2021-04-27 11:54
Motivating example:

>>> @dataclass
... class A:
...   x: InitVar[int] = 0
...   y: int = 1
... 
>>> a = A()
>>> a.x
0
>>> a.y
1

PEP-557 does not specify if fields annotated with InitVar[...] are available on the resulting dataclass. However, they are not part of the dataclass structure and are only used for __*init__ generation, so perhaps they shouldn't be? Wdyt?
msg392065 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2021-04-27 12:46
This is just how Python works. The default values for .x and .y are set on the class A, not its instances. Here's the equivalent without dataclasses:

>>> class A:
...   x = 0
...   y = 1
...
>>> a = A()
>>> a.x
0
>>> a.y
1
>>> a.__dict__
{}
>>> A.__dict__
mappingproxy({'__module__': '__main__', 'x': 0, 'y': 1, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None})

Note that the instance "a" has nothing in its __dict__, but the values A.x and A.y are none the less available through the instance "a".

The only way to avoid this would be for @dataclass to delete the values from A, but that's not a change I'd be willing to make.

Is this causing some actual problem in any code?
msg392070 - (view) Author: Sergei Lebedev (superbobry) * Date: 2021-04-27 13:17
I understand that this is a side-effect of having a default value, but I was hoping we could delattr InitVar's in @dataclass. 

I'm not aware of this causing problems, but it does feel a bit unsatisfying that InitVar's with defaults are kept in the class namespace. 

Do you see what could go wrong if we delete them?
msg392071 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2021-04-27 13:22
I'm not aware of what problems it would cause, but there's no doubt someone who's relying on it.

Since it's a behavior of normal classes, changing it would violate dataclasses desire (not always realized) to have as little impact as possible on the class that it's decorating.

You could add another decorator to do this, or handle it in a __post_init__ function if needed.
msg392876 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2021-05-04 11:36
I don’t see any way of changing this behavior, so I’m going to close this issue.
History
Date User Action Args
2022-04-11 14:59:44adminsetgithub: 88119
2021-05-04 11:36:01eric.smithsetstatus: open -> closed
resolution: rejected
messages: + msg392876

stage: resolved
2021-04-27 13:22:38eric.smithsetmessages: + msg392071
2021-04-27 13:17:51superbobrysetmessages: + msg392070
2021-04-27 12:57:34eric.smithsetassignee: eric.smith
type: behavior
versions: - Python 3.7, Python 3.8, Python 3.11
2021-04-27 12:46:28eric.smithsetmessages: + msg392065
2021-04-27 11:54:00superbobrycreate