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

Brett Cannon brett at python.org
Mon May 15 14:18:10 EDT 2017

On Mon, 15 May 2017 at 10:32 Guido van Rossum <guido at python.org> wrote:

> On Mon, May 15, 2017 at 9:50 AM, Brett Cannon <brett at python.org> wrote:
>> On Mon, 15 May 2017 at 08:30 Guido van Rossum <guido at python.org> wrote:
>>> This should be worked into a PEP, instead of living on as a bunch of
>>> python-ideas posts and blogs.
>>> I find the attrs documentation (and Glyph's blog post about it) almost
>>> unreadable because of the exalted language -- half the doc seems to be
>>> *selling* the library more than *explaining* it. If this style were to
>>> become common I would find it a disturbing trend.
>>> But having something alongside NamedTuple that helps you declare classes
>>> with mutable attributes using the new PEP 526 syntax (and maybe a few
>>> variants) would definitely be useful. Will someone please write a PEP? Very
>>> few of the specifics of attrs need be retained (its punny naming choices
>>> are too much for the stdlib).
>> In case someone decides to take this on, I wrote a blog post back in
>> March that shows how to use __init_subclass__() to do a rough approximation
>> of what Guido is suggesting:
>> https://snarky.ca/customizing-class-creation-in-python/ .
>> Based on my thinking on the topic while writing my blog post, the tricky
>> bit is going to be deciding how to handle default values (i.e. if you set a
>> default value like `attr: int = 42` on the class definition then you have
>> `cls.attr` exist which might not be what you want if you would rather have
>> the default value explicitly set on every instance but not fall through to
>> the class (e.g. `del ins.attr; ins.attr` raises an AttributeError instead
>> of falling through to `cls.attr`). You could remove the default from the
>> class in your __init_subclass__(), but then you have to decide if that's
>> too unexpected/magical for someone looking at the code.
> I would personally prefer the initializer to stay in the class in cases
> like this. If the initializer needs to be a default instance of a mutable
> class (e.g. an empty list or dict) there could be a special marker to
> indicate that, e.g.
>   attacks: List[int] = MAKE_NEW  # Creates a new [] for each instance
> while if the default needs to be something more custom it could be a
> similar marker with a callable argument, e.g.
>   fleet: Dict[str, str] = MAKE_NEW(lambda: {'flagship': 'Enterprise'})
> I would prefer not to have cleverness like initialization with a callable
> automatically does something different.

So if I'm understanding your idea correctly:

  class Foo(DataClass):
      attr: int = 42

would leave Foo.attr alone, but:

  class Foo(DataClass):
      attr: int = MAKE_NEW(42)

would be the way to flag that `Foo.attr` shouldn't exist (I'm assuming both
options would flag that there should be an `attr` argument to __init__())?

>> And I too would be interested in seeing something like this, if for any
>> other reason than to help people not to misuse NamedTuple for
>> quick-and-dirty data objects in new APIs (NamedTuple is meant to help move
>> old-style tuple-based APIs to a class-based one).
> Not sure I agree that is its only purpose.

My typical thinking on this is I don't want the tuple API that comes with
NamedTuple for new APIs, and so that's when I reach for
types.SimpleNamespace and have a function that controls the constructor so
I can provide a concrete initializer API (e.g. `def foo(a, b): return
types.SimpleNamespace(a=a, b=b)`).


> --
> --Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20170515/669a0771/attachment-0001.html>

More information about the Python-ideas mailing list