Re: Auto assignment of attributes

Bringing this back on list -- I hope that was an accident. (NOTE: getting a touch off-topic here -- but I do bring it back around at the end) On Wed, May 4, 2022 at 4:38 AM Paul Moore <p.f.moore@gmail.com> wrote:
Agreed here -- I'm probably responsible for much of the talk about dataclasses, so sorry about that. In fact, my only point there was that dataclasses are a solution to the "I'm writing many versions of self.x = x in my __init__ method, and that seems unnecessary" problem, and that I think that very problem is the strongest case for auto-assignment. Ergo, auto-assignment isn't a critical feature.
Agreed -- if it's a complex case, neither datclasses nor auto-assignment would help. I've used attrs, which has field converters. ...
The problem with __post_init__ (I think) is that it confuses the type checkers (beware, untested code below!):
Does the attrs approach work any better for this? @dataclass
Frankly, I see that as a limitation of static typing -- how does one describe "anything that can be turned into a Version? -- sure, the Version __init__ can take either a Version or a str -- but only certain strs will make any sense -- so what's the point? Honestly, I think if you want your code to be statically "safe" then you should have this metadata class require a Version object, which would require its users to do the conversion first. Which is why I like the Dynamic nature of Python, and haven't gotten excited about static typing. I suppose the way to solve this without dataclasses or auto-assignment is to type the class attribute and the __init__ parameter separately, yes? (which auto-assignment wouldn't help with, either) (untested, and probably wrong, 'cause I'm not that familiar with typing) Class Metadata: version: Version ... def __init__(self, version: Version | str, ...): ... Is that right? What this tells me is that if you want dataclasses to be more typing-friendly, then there should be a way to specify the __init__ type separately, which could be done with a parameter to the Field object. Bringing it back OT: As much as I hate to say it: For folks advocating an auto-assignment feature -- you should probably consider how it would play with static typing :-( -CHB
-- Christopher Barker, PhD (Chris) Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython

On Wed, 4 May 2022 at 17:04, Christopher Barker <pythonchb@gmail.com> wrote:
Bringing this back on list -- I hope that was an accident.
If it was, it was me not spotting that your reply to me was on-list, I thought you're replied offlist so I followed suit. Not a problem though, I'm fine with this being on-list (although we're quite a lot off topic now, so others may want me to shut up ;-))
Not notably. But I haven't explored it in detail, I'll be honest - there's a lot of options, and I may have missed a good one.
Well, while I do agree it's a limitation of static typing, if a value is passed to Version(), the type checker can infer that it must have a type that matches the argument declaration. The problem is that there's no way in Python to *describe* that type so that I can use it in the attribute declaration. So I have to copy the definition. And anyway, what I want is to say that the *attribute* has type Version, but the *constructor argument* has a different type. And I don't think type checkers can handle that, because of how dataclasses work (auto-generating the init function).
Honestly, I think if you want your code to be statically "safe" then you should have this metadata class require a Version object, which would require its users to do the conversion first.
Nope, I really shouldn't. The reasons are very specific to the application logic, but a class that required the user to convert in advance would be useless to me. (Sure, a complete redesign of the app might make it possible, but that's not the point).
Which is why I like the Dynamic nature of Python, and haven't gotten excited about static typing.
I know, and I agree. But having autocompletion in VS Code is nice, and mypy checks do sometimes pick up on errors. But too much of my time is taken up trying to work around cases where type checkers get confused or upset about very dynamic code. And they don't typically degrade gracefully (by which I mean red "you got this wrong" error bars in my editor, or errors I don't know how to suppress in mypy without adding "I know what I'm doing" comments in my code. So I'm mostly uninterested in adding types, but when I do, I'm obsessive about getting them right :-(
I suppose the way to solve this without dataclasses or auto-assignment is to type the class attribute and the __init__ parameter separately, yes?
Possibly, I haven't experimented much. Although it's a PITA if, in def f(v): v1 = Version(v) reveal_type(v1) reveal_type(v) type checkers can't infer that v1 is of type Version, and v is of a type compatible with the argument of Version. Annoyingly, VS Code appears to get the type of v1, but not of v. And mypy says: ❯ mypy .\tyex.py tyex.py:5: note: Revealed type is "Any" tyex.py:5: note: 'reveal_type' always outputs 'Any' in unchecked functions tyex.py:6: note: Revealed type is "Any" tyex.py:6: note: 'reveal_type' always outputs 'Any' in unchecked functions
(which auto-assignment wouldn't help with, either)
Indeed. [...]
What this tells me is that if you want dataclasses to be more typing-friendly, then there should be a way to specify the __init__ type separately, which could be done with a parameter to the Field object.
Maybe. But really what I want is a way to say "this is what type the attribute is, but don't assume the init argument is the same type". Or just not bother with all this at all. This is where it starts to just become not worth trying to make dataclasses do what I want, I might as well do it myself via init=False.
Bringing it back OT:
As much as I hate to say it: For folks advocating an auto-assignment feature -- you should probably consider how it would play with static typing :-(
That's probably a good point. Paul

On Wed, 4 May 2022 at 17:04, Christopher Barker <pythonchb@gmail.com> wrote:
Bringing this back on list -- I hope that was an accident.
If it was, it was me not spotting that your reply to me was on-list, I thought you're replied offlist so I followed suit. Not a problem though, I'm fine with this being on-list (although we're quite a lot off topic now, so others may want me to shut up ;-))
Not notably. But I haven't explored it in detail, I'll be honest - there's a lot of options, and I may have missed a good one.
Well, while I do agree it's a limitation of static typing, if a value is passed to Version(), the type checker can infer that it must have a type that matches the argument declaration. The problem is that there's no way in Python to *describe* that type so that I can use it in the attribute declaration. So I have to copy the definition. And anyway, what I want is to say that the *attribute* has type Version, but the *constructor argument* has a different type. And I don't think type checkers can handle that, because of how dataclasses work (auto-generating the init function).
Honestly, I think if you want your code to be statically "safe" then you should have this metadata class require a Version object, which would require its users to do the conversion first.
Nope, I really shouldn't. The reasons are very specific to the application logic, but a class that required the user to convert in advance would be useless to me. (Sure, a complete redesign of the app might make it possible, but that's not the point).
Which is why I like the Dynamic nature of Python, and haven't gotten excited about static typing.
I know, and I agree. But having autocompletion in VS Code is nice, and mypy checks do sometimes pick up on errors. But too much of my time is taken up trying to work around cases where type checkers get confused or upset about very dynamic code. And they don't typically degrade gracefully (by which I mean red "you got this wrong" error bars in my editor, or errors I don't know how to suppress in mypy without adding "I know what I'm doing" comments in my code. So I'm mostly uninterested in adding types, but when I do, I'm obsessive about getting them right :-(
I suppose the way to solve this without dataclasses or auto-assignment is to type the class attribute and the __init__ parameter separately, yes?
Possibly, I haven't experimented much. Although it's a PITA if, in def f(v): v1 = Version(v) reveal_type(v1) reveal_type(v) type checkers can't infer that v1 is of type Version, and v is of a type compatible with the argument of Version. Annoyingly, VS Code appears to get the type of v1, but not of v. And mypy says: ❯ mypy .\tyex.py tyex.py:5: note: Revealed type is "Any" tyex.py:5: note: 'reveal_type' always outputs 'Any' in unchecked functions tyex.py:6: note: Revealed type is "Any" tyex.py:6: note: 'reveal_type' always outputs 'Any' in unchecked functions
(which auto-assignment wouldn't help with, either)
Indeed. [...]
What this tells me is that if you want dataclasses to be more typing-friendly, then there should be a way to specify the __init__ type separately, which could be done with a parameter to the Field object.
Maybe. But really what I want is a way to say "this is what type the attribute is, but don't assume the init argument is the same type". Or just not bother with all this at all. This is where it starts to just become not worth trying to make dataclasses do what I want, I might as well do it myself via init=False.
Bringing it back OT:
As much as I hate to say it: For folks advocating an auto-assignment feature -- you should probably consider how it would play with static typing :-(
That's probably a good point. Paul
participants (3)
-
Christopher Barker
-
Eric V. Smith
-
Paul Moore