I take the freedom to interpret 'no news == good news' on this thread -
nominally that there are no major disagreements that a decorator
to auto-commit `__init__` atributes to the instance could be a nice addition
to the stdlib.

I also assume it is uncontroversial enough for not needing a PEP.

I remember a similar thread from a couple years ago where the thread ended
up agreeing on such a decorator as well.

I would then like to take the opportunity to bike-shed  a bit on this, and
maybe we
can get out of here with a BPO and an actual implementation.

So,

1) Would it live better in "dataclasses" or "functools"? Or some other
package?

2) What about: the usage of the decorator without arguments would imply in
committing all of
`__init__` arguments as instance attributes, and two, mutually exclusive,
optional kwonly
 "parameters" and "except" parameters could be used with a list of
arguments to set?

2.1)  The usage of a "parameters" argument to the decorator would even pick
names from an
eventual "**kwargs" "__init__" parameter, which otherwise would be
commited be left alone/
2.2) would it make sense to have another argument to specify how "**kwargs"
should be treated?
I see three options: (i) ignore it altogether, (ii) commit it  as a
dictionary, (iii) commit all keys in kwargs as
instance attributes, (iii.a) "safe commit" keys in kwargs, avoiding
overriding methods and class attributes.
    (whatever the option here, while the principle of "less features are
safer" in a first release, should consider
     if it would be possible to include the new features later in a
backwards compatible way)

3) While the Python implementation for such a decorator is somewhat
straightforward, are there any chances
of making it static-annotation friendly? AFAIK dataclasses just work with
static type checking because
the @dataclass thecorator is special-cased in the checker tools themselves.
Would that be the same case here?

4) Naming. What about "@commitargs"?

5) Should it emit a warning (or TypeError) when decorating anything but a
function named `__init__ ` ?



On Wed, Apr 20, 2022 at 3:14 PM Joao S. O. Bueno <jsbu...@python.org.br>
wrote:

>
>
> On Wed, Apr 20, 2022 at 12:30 PM Pablo Alcain <pabloalc...@gmail.com>
> wrote:
>
>>
>> Regarding the usage of a decorator to do the auto-assignment, I think
>> that it has an issue regarding how to select a subset of the variables that
>> you would be setting. In the general case, you can probably get away with
>> calling `autoassign`. But, for example, if you want to set a but not b,
>> you'd probably have to use a string as the identifier of the parameters
>> that you want to assign:
>>
>> ```
>> class MyKlass:
>>     @autoassign('a')
>>     def __init__(self, a, b):
>>         print(b)
>>
>> ```
>>
>> This, in my perspective, brings two things: the first one is that you'd
>> be repeating everywhere the list of names, so for example doing refactors
>> like changing a variable name would be a bit error-prone: If you change the
>> variable from `a` to `my_var_name`, you'd have to also change the list in
>> the autoassign. It's not a lot, but it can induce some errors because of
>> the repetition. On the other hand, I guess it would be a bit hard for IDEs
>> and static checkers to follow this execution path. I know that I'm only one
>> data point, but for what it's worth, I was very excited with the idea but
>> this prevented me from actually implementing this solution on a day-to-day
>> basis: it felt a bit fragile and induced me to some errors.
>>
>
> IMO, that is trivially resolvable by doing the decorator, by default,
> assign all parameters. If it tkaes a string or sequence with parameter
> names, then, it will just bind those (still shorter than one line
> `self.attr = attr` for each attribute.
>
> And for the fragility: that is the advantage of having a robust
> implementation of something like this on the stdlib: it is not something
> most people will go out of their way to write their own, since the tradeoff
> is just
> copy and paste a bunch of plain assignments.
>
> But having it right and known, could chop off tens of lines of useless
> code in, probably the majority of Python projects.
>
>
> Also answering Christopher Barker:
>
> This has a subtle, but different use than dataclasses.
> It might be grouped in the dataclasses module, on the stdlib.
>
>
>
>>
>> About dataclasses, the point that Chris mentions, I think that they are
>> in a different scope from this, since they do much more stuff. But, beyond
>> this, a solution on the dataclass style would face a similar scenario:
>> since the `__init__` is autogenerated, you would also be in a tight spot in
>> the situation of "how would I bind only one of the items?". Again, now I'm
>> talking about my experience, but I think that it's very hard to think that
>> we could replace "classes" with "dataclasses" altogether. Here's an example
>> of one of the (unexpected for me) things that happen when you try to do
>> inheritance on dataclasses: https://peps.python.org/pep-0557/#inheritance
>> .
>>
>> Overall, I think that it's hard to think about a solution to this problem
>> that is clean and robust without adding new syntax with it. I would like to
>> hear your thoughts on this (and everyone else's of course!)
>>
>> Cheers,
>> Pablo
>>
>> On Mon, Apr 18, 2022 at 9:55 PM Christopher Barker <python...@gmail.com>
>> wrote:
>>
>>> On Mon, Apr 18, 2022 at 4:24 PM Joao S. O. Bueno <jsbu...@python.org.br>
>>> wrote:
>>>
>>>> I for one am all for the inclusion of a decorator targeting either the
>>>> __init__ method
>>>> or the class itself to perform this binding of known arguments to
>>>> instance attributes
>>>> prior to entering __init__. It could live either in functools or
>>>> dataclasses itself.
>>>>
>>>
>>> Isn’t this what dataclasses already accomplish? I understand that it’s
>>> the reverse— with a dataclass, you specify the fields, and the __init__ is
>>> generated, whereas this proposal is ttt be at you’d write an __init__, and
>>> the attributes would be set — but other than taste, is there a practical
>>> difference?
>>>
>>> -CHB
>>>
>>>
>>>> On Sat, Apr 16, 2022 at 5:49 PM Pablo Alcain <pabloalc...@gmail.com>
>>>> wrote:
>>>>
>>>>> The problem of assigning init arguments as attributes has appeared
>>>>> several times in the past (
>>>>> https://mail.python.org/archives/list/python-ideas@python.org/message/VLI3DOFA5VWMGJMJGRDC7JZTRKEPPZNU/
>>>>> was the most recent we could find) and is already handled in dataclasses.
>>>>>
>>>>> Lately, discussing this topic with a friend, we thought that using a
>>>>> specific token could be a possible approach, so you could do:
>>>>>
>>>>> class MyClass:
>>>>>
>>>>>     def __init__(self, @a, @b, c):
>>>>>
>>>>>         pass
>>>>>
>>>>> and it would be analogous to doing:
>>>>>
>>>>> class MyClass:
>>>>>
>>>>>     def __init__(self, a, b, c):
>>>>>
>>>>>         self.a = a
>>>>>
>>>>>         self.b = b
>>>>>
>>>>> Then, you would instantiate the class as usual, and the variables
>>>>> tagged with `@` would be bound to the object:
>>>>>
>>>>> >>> objekt = MyClass(2, 3, 4)
>>>>>
>>>>> >>> print(objekt.b)
>>>>>
>>>>> 3
>>>>>
>>>>> >>> print(objekt.c)
>>>>>
>>>>> AttributeError: 'MyClass' object has no attribute 'c'
>>>>>
>>>>>
>>>>> We have a working implementation here if anyone wants to take a look
>>>>> at: https://github.com/pabloalcain/cpython/tree/feature/auto_attribute.
>>>>> Keep in mind that we have limited knowledge about how to modify cpython
>>>>> itself, and which would the best places be to do the modifications, so 
>>>>> it's
>>>>> more than likely that some design decisions aren't very sound (
>>>>> https://devguide.python.org/grammar/ and
>>>>> https://devguide.python.org/parser/ were incredibly helpful).
>>>>>
>>>>> Besides the implementation, we would like to know what the community
>>>>> thinks on whether this might have any value. While developing this, we
>>>>> realized that Crystal already has this feature (eg
>>>>> https://github.com/askn/crystal-by-example/blob/master/struct/struct.cr)
>>>>> with the same syntax; which is kind of expected, considering it's syntax 
>>>>> is
>>>>> based on Ruby.
>>>>>
>>>>>
>>>>> Random collection of thoughts:
>>>>>
>>>>> 1. If auto-assignment made sense in general, one of the reasons we
>>>>> went for this rather than the decorator approach is that we wouldn't like
>>>>> to have a list of strings that can vary decoupled from the actual argument
>>>>> name.
>>>>>
>>>>> 2. The current implementation of `@` works for any function, not only
>>>>> init. We don't know if this would actually be a desirable feature.
>>>>>
>>>>> 3. It also works with any function in the wild. This mostly allows for
>>>>> monkey-patching to work out of the box:
>>>>>
>>>>> >>> class Klass:
>>>>>
>>>>> ...     def __init__(self):
>>>>>
>>>>> ...         pass
>>>>>
>>>>> ...
>>>>>
>>>>> >>> def add_parameter(k, @p):
>>>>>
>>>>> ...     pass
>>>>>
>>>>> ...
>>>>>
>>>>> >>> Klass.add_parameter = add_parameter
>>>>>
>>>>> >>> objekt = Klass()
>>>>>
>>>>> >>> print(objekt.p)
>>>>>
>>>>> Traceback (most recent call last):
>>>>>
>>>>>   File "<stdin>", line 1, in <module>
>>>>>
>>>>> AttributeError: 'Klass' object has no attribute 'p'
>>>>>
>>>>> >>> objekt.add_parameter(11)
>>>>>
>>>>> >>> print(objekt.p)
>>>>>
>>>>> 11
>>>>>
>>>>> Again, we are not sure if this is desirable, but it's what made most
>>>>> sense for us at the moment.
>>>>>
>>>>> 4. Adding the `@` token to the argument doesn’t remove the variable
>>>>> from the function/method scope, so this would be perfectly valid:
>>>>>
>>>>> >>> def my_function(k, @parameter):
>>>>>
>>>>> ...     print(parameter)
>>>>>
>>>>> >>> my_function(objekt, 4)
>>>>>
>>>>> 4
>>>>>
>>>>> >>> k.parameter
>>>>>
>>>>> 4
>>>>>
>>>>>
>>>>>
>>>>> 5. We didn’t implement it for lambda functions.
>>>>>
>>>>> Cheers,
>>>>>
>>>>> Pablo and Quimey
>>>>>
>>>>> _______________________________________________
>>>>> Python-ideas mailing list -- python-ideas@python.org
>>>>> To unsubscribe send an email to python-ideas-le...@python.org
>>>>> https://mail.python.org/mailman3/lists/python-ideas.python.org/
>>>>> Message archived at
>>>>> https://mail.python.org/archives/list/python-ideas@python.org/message/SCXHEWCHBJN3A7DPGGPPFLSTMBLLAOTX/
>>>>> Code of Conduct: http://python.org/psf/codeofconduct/
>>>>>
>>>> _______________________________________________
>>>> Python-ideas mailing list -- python-ideas@python.org
>>>> To unsubscribe send an email to python-ideas-le...@python.org
>>>> https://mail.python.org/mailman3/lists/python-ideas.python.org/
>>>> Message archived at
>>>> https://mail.python.org/archives/list/python-ideas@python.org/message/HUGRGXVT7NBWSXI2ILZOMFIRWV4KIQ5Q/
>>>> Code of Conduct: http://python.org/psf/codeofconduct/
>>>>
>>> --
>>> Christopher Barker, PhD (Chris)
>>>
>>> Python Language Consulting
>>>   - Teaching
>>>   - Scientific Software Development
>>>   - Desktop GUI and Web Development
>>>   - wxPython, numpy, scipy, Cython
>>>
>>
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/UBC3DCLMVF5JC5MRQL7EDT6F3NL6PBRC/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to