<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Mon, 15 May 2017 at 10:32 Guido van Rossum <<a href="mailto:guido@python.org">guido@python.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, May 15, 2017 at 9:50 AM, Brett Cannon <span dir="ltr"><<a href="mailto:brett@python.org" target="_blank">brett@python.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><br><div class="gmail_quote"><span><div dir="ltr">On Mon, 15 May 2017 at 08:30 Guido van Rossum <<a href="mailto:guido@python.org" target="_blank">guido@python.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>This should be worked into a PEP, instead of living on as a bunch of python-ideas posts and blogs.<br><br>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.<br><br>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).<br></div></div></blockquote><div><br></div></span><div>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: <a href="https://snarky.ca/customizing-class-creation-in-python/" target="_blank">https://snarky.ca/customizing-class-creation-in-python/</a> .</div><div><br></div><div>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.</div></div></div></blockquote><div><br></div></div></div></div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>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.<br><br></div><div>  attacks: List[int] = MAKE_NEW  # Creates a new [] for each instance<br><br></div><div>while if the default needs to be something more custom it could be a similar marker with a callable argument, e.g.<br><br></div><div>  fleet: Dict[str, str] = MAKE_NEW(lambda: {'flagship': 'Enterprise'})<br><br></div><div>I would prefer not to have cleverness like initialization with a callable automatically does something different.<br></div></div></div></div></blockquote><div><br></div><div>So if I'm understanding your idea correctly:</div><div><br></div><div>  class Foo(DataClass):</div><div>      attr: int = 42</div><div><br></div><div>would leave Foo.attr alone, but:</div><div><br></div><div>  class Foo(DataClass):</div><div>      attr: int = MAKE_NEW(42)</div><div><br></div><div>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__())?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div></div></div></div></div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div>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).</div></div></div></blockquote></div></div></div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"></div><br></div><div class="gmail_extra">Not sure I agree that is its only purpose.<br></div></div></blockquote><div><br></div><div>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)`).</div><div><br></div><div>-Brett</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"></div></div><div dir="ltr"><div class="gmail_extra"><br>-- <br><div class="m_-5510517250624622907gmail_signature" data-smartmail="gmail_signature">--Guido van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)</div>
</div></div></blockquote></div></div>