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/

Reply via email to