[Python-ideas] JavaScript-Style Object Creation in Python (using a constructor function instead of a class to create objects)

Todd toddrjen at gmail.com
Wed May 17 10:28:52 EDT 2017


On May 17, 2017 04:16, "Michel Desmoulin" <desmoulinmichel at gmail.com> wrote:



Le 17/05/2017 à 07:22, Guido van Rossum a écrit :
> On Tue, May 16, 2017 at 8:14 PM, Juancarlo Añez <apalala at gmail.com
> <mailto:apalala at gmail.com>> wrote:
>
>     What I like about attrs is:
>
>       * The class level declaration of instance attributes
>       * That the reasonable *init*, *repr*, and *eq* are generated
>
> OK, the former should be doable using PEP 526 (the type is stored in
> __annotations__ and the default in the class dict given to the
> metaclass), while the latter should be doable using a standard metaclass
> -- assuming we can agree on what the "reasonable" __init__, __repr__ and
> __eq__ should do.
>
>
>     I don’t like the excessive wordiness in attrs,
>
> Really? @attr.s is wordy? :-) I think it's deadly cute. (The only
> library I've ever seen that did something worse was "monocle" which used
> @_o.)

>>> import attr
>>> @attr.s
... class Point:
...     x = attr.ib(default=42)
...     y = attr.ib(default=attr.Factory(list))


Is pretty wordy compared to something like another language would do
such as:

class Point:
   int x = 42
   list y = []

Now I get that:

- Python already has a similar syntax creating class attributes.
- You can't put mutable objects here.
- attr does more since it generates dunder methods.

But having an import, a decorator and verbose calls to attr.ib does not
feel like idiomatic Python at all. Python is an elegant and expressive
language. This is none of the above. Also Python is beginner friendly.
Now OPP is already hard to teach to my students, but if I have to add
this to the mix, I will just have to tell them to copy / paste it
blindly for a long time before I can get to the point they can
understand what it does.

We should be able to find a middle ground.

First, if we have something LIKE attr, should it need an import? Basic
data structures may not require an import to work. async/await are way
better than import @asyncio.coroutine.

Secondly, while I really, really, really want this feature, I think we
should not rush it.

Some ideas have to be explored.

E.G:

Adding keywords for it ? I know adding a keyword is the worst thing one
can suggest on this list ever. But it has to be mentioned because most
other languages do it this way.

class Point:
    instancevar x = 42
    instancevar y = lazy [] # we add a debate about this a few months ago


Adding a special syntax for it ? ruby has something similar.

class Point:
    @x = 42
    @@y = list

Upgrading the class constructor? It does not address the mutablility
issue though.

class Point(x=42, y=[])

Mixing concepts?


class Point(metaclass=autoclass(x=42, y=lazy [])):
    pass

@args(x=42)
@factory_args(y=list)
@autodunder()
class Point:
    pass

@autoclass(
    x=42
    y=autoclass.lazy(list)
)
class Point:
    pass


Just adding attrs, which is a workaround to a missing feature in Python,
as a boiler plate and calling it a day seems unwise.

Don't get me wrong, I like attrs, I like asyncio and I like the whole
battery included concept. But we lived without it until now, so let's
not go too fast on this.



What about an attribute-level decorator-like syntax, like:

class Point:
    @instattr x = 42
    @instattr @lazy y = []

Or:

class Point:
    @instattr: x = 42
    @instattr: @lazy: y = []

This would have the benefit of a keyword-like syntax without actually
needing a new keyword.

The question is how such a system would work in a general manner. Of course
these aren't decorators, something new would be needed.  I see two main
approaches.

1. These functions are called both at class creation and initialization
time with arguments that let it decide what to do. So perhaps it is given
whatever is on the right side of the "=", the class, and the class instance
(which is None at class creation time).  Perhaps it is given the variable
name as a string, or perhaps Python magically adds the name to the
namespace whenever the function returns. Alternatively, this could be a
class and there are two dunder methods that are called at class creation
time and class initialization time.

2. These are called at attribute access time. Python sets up the attribute
as a special property, and whenever the attribute is accessed the function
is given arguments that allow it to infer what is going on. It then
controls if and how the variable is accessed. Alternatively, this could be
a class and there are dunder methods called at various times.

The second approach would be more flexible, while the first approach would
require less work for developers for basic tasks. The two approaches are
not mutually-exclusive, either, especially if a dunder method-based
approach is used.

I know that strictly speaking the property-based approach could be
implemented in the function-based approach, but that would be a lot more
work.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20170517/c1721199/attachment.html>


More information about the Python-ideas mailing list