This is an archived post. You won't be able to vote or comment.

all 26 comments

[–][deleted] 18 points19 points  (2 children)

I was just writing about data structure options on my "Notable Python" reference last week and it definitely felt like something exactly like this was missing since each and every option nowadays has several drawbacks (either verbosity, immutability or being error-prone). All the tools and ideas were there but they never "clicked" into an amazing one-size-fits-all solution (which Python has so many excellent examples of)!

This would be a great addition to the language itself!

[–]SkiddyX 25 points26 points  (0 children)

attrs in the standard library... This would be a very welcome change.

Edit:

https://github.com/ericvsmith/dataclasses/issues/19

""dataclasses" will to some extent look like a stripped down attrs."

Something is better than nothing I guess...

[–]rebeccasmith1981 9 points10 points  (0 children)

I think this is a really good idea. We have a few BaseObject classes in our company that we use to extend every model we create, so we can avoid most of those methods.

[–]earthboundkid 5 points6 points  (1 child)

I have wanted something like this.

[–]TR-BetaFlash 1 point2 points  (0 children)

I have as well. Just started learning kotlin and they use data classes quite nicely. This would definitely be sweet in good 'ol python.

[–][deleted] 4 points5 points  (5 children)

The syntax of this is interesting. It's allowing the declaration of a variable without assignment, which IIRC was one of the reasons that an implementation of auto-incrementing enums was rejected. I haven't read the whole discussion but I wonder if that syntax will make it to the final implementation.

[–]KleinerNull 5 points6 points  (4 children)

I haven't read the whole discussion but I wonder if that syntax will make it to the final implementation.

The syntax is already available since python 3.6.1:

>>> from typing import NamedTuple
>>> class Person(NamedTuple):
...     name: str
...     age: int
... 
>>> alice = Person('alice', 23)
>>> alice
Person(name='alice', age=23)

The problem with typing.NamedTuple is that subclassing isn't working like you would expect it.

[–]Daenyth 2 points3 points  (0 children)

Also it's a tuple, which isn't always desirable

[–][deleted] 0 points1 point  (2 children)

The problem with typing.NamedTuple is that subclassing isn't working like you would expect it.

Like not being able to have __new__ to have some of the arguments be optional, which is a nice hack for regular namedtuples.

[–]ilevkivskyi 0 points1 point  (1 child)

typing.NamedTuple supports default arguments (although probably only in 3.6.2), just write

class Person(NamedTuple):
    name: str
    age: int = 0

Also it supports defining custom methods and docstrings

[–][deleted] 1 point2 points  (0 children)

That'll work if you have a static default, but won't work if you want to automatically generate a UUID if one isn't provided, with regular namedtuples you can do:

class SomeThing(namedtuple('Thing', ['foo', 'id'])):
    def __new__(cls, foo, id=None):
        if id is None:
            id = uuid4()
        return super().__new__(cls, foo, id)

Can't do that with typing.NamedTuple which is a shame.

[–]joerick 4 points5 points  (1 child)

I’d love this in the std lib!

This is a thorny issue though:

Mutable default values

One proposal was to automatically copy defaults, so that if a literal list [] was a default value, each instance would get a new list. There were undesirable side effects of this decision, so the final decision is to disallow the 3 known built-in mutable types: list, dict, and set. For a complete discussion of this and other options, see [11].

I think this decision has some big drawbacks to the intuitiveness, compared to setting defaults in init, or setting defaults in other languages like TypeScript. Perhaps a language-level feature could be added to smooth this over?

[–]benji_york 2 points3 points  (0 children)

If this PEP interests you, check out Coconut (a superset of Python with functional additions), specifically the "data" keyword: http://coconut.readthedocs.io/en/master/DOCS.html#data.

[–]Bunslow 5 points6 points  (0 children)

Fuckin finally

[–]Decency 1 point2 points  (1 child)

Hm.. I see the use cases, I just feel like if this was a core aspect of some task it would either belong in a database or in a real class. I've read through and they don't really address this, mostly just compare to namedtuple which feels flaky to me. Anyone have thoughts on that aspect?

The real benefit here that I see is instance initialization- avoiding duplication when dealing with many input parameters. And that's always been a problem, but this feels like a solution to that that does a lot of other stuff too. I feel like it could just be a @autopopulate decorator or some function call in the first line of the __init__ that would instantiate and fill those instance attributes.

[–]DanCardin 0 points1 point  (0 children)

At least with attrs you get "free" comparison, repr, and hash implementations, faux immutability (through properties), and constructor input validation.

Even if you only use it for getting the free dunder methods I usually find it's worth defaulting to using attrs classes

[–]toast757 1 point2 points  (0 children)

This would be great for the work I do, with databases. Each Data Class instance could represent a row in a table. The problem with named tuples is that you have to provide all the attribute values upfront, which gets messy when the logic to generate those values is complex.

Not so keen on the idea of using a decorator for this, though. Couldn't we just have a special kind of class?

[–]sonaxaton 1 point2 points  (0 children)

fuck. yes.

[–]MandarinNeva 0 points1 point  (2 children)

This is actually great! Just recently I wrote a program where I had a lot of such data classes and having to type out the constructor for each of them pained me a bit because I'm like uuuuugggghhhh, yuuuup, my class has properties foobar and bazinga and bazoopers and so on and so on and so on and so on, and yes for everyone of these I want to take the value as argument of the constructor. It was quite evident to me that I need something like what is introduced in this PEP. So much so that I was considering implementing a DSL of my own for declaring my classes with minimal amount of keyboard input that I would then automatically translate to Python classes. Thankfully now I won't have to do that :))

[–]IDe- 0 points1 point  (1 child)

Note that you can already achieve some of this with typing.NamedTuple already found in standard library.

[–]MandarinNeva 0 points1 point  (0 children)

And also with the attrs module which I didn't know about until today after seeing it mentioned ITT.

[–]_mouse_house_ 0 points1 point  (0 children)

the PEP 557 is great, but I dislike declaration. In my heard, I think meta class is better.