24 ms·
Attrs – the Python library everyone needs (2016)
- gjvc 5y agosee also "dataclasses" since python 3.7
- nmca 5y agocounterpoint: stdlib is where things go to die
- falafelite 5y agoCame here to say this, dataclasses have been super helpful for a big part of the pain point highlighted by the author. More often than not, that is enough for me.
- avidphantasm 5y agoYes. There needs to be a very good reason for me to pull in a third party library (in this day and age, given supply chain attacks, etc.). I don’t see what Attrs gives me that dataclasses does not.
- 4ec0755f5522 5y agoPython's STL is such that using it is a code smell. It's better to just use the right tool for the job: you are almost guaranteed to need at least one external library/module for any project of even moderate complexity. So bite the bullet, invest in the time/tooling to do packaging correctly, and use the very excellent Python ecosystem (isn't it why you are using Python to begin with?) that you have at your disposal. Sticking with the "rusty, leaking batteries included!" in the STL is a bad call and I don't believe it is safe, either; most of the STL is abandonware that is just being shipped for backward compatibility sake. Don't make future product decisions, design decisions etc. based on Python teams' deprecation requirements! I've been writing Python a long time and have grown quite frustrated by some of its warts. But every time I look at seriously investing in another language attrs is one of the few things I wouldn't want to give up. It's not perfect but I'll take very, very good when I can get it, yeah?
- dreamofkoholint 5y agoHonestly, only use python because I have to. I don't think it belongs inside a decently sized software product Others disagree, though, so I must use it What you're saying only bolsters my opinion
- geofft 5y agoHuh, it's the other way around for me. Just about every nontrivial Python project I write requires at least one third-party library, and one much more complicated than attrs at that, that I may as well use attrs too. All the complexity of having dependencies - both distributing them / setting up a virtualenv / etc., and whatever scrutiny I wish to do on dependencies - have a pretty big constant term from doing them at all; doing them for one more dependency (and one that doesn't change all that often) is only a bit more work. Granted, I'm not reviewing my third-party dependencies line by line when I upgrade them. But also I'm more afraid of the security risks of large amounts of in-house code that aren't exposed to public scrutiny, and so a policy that dissuaded the use of even high-quality and well-regarded third-party dependencies seems like it would do more harm than good. Besides that, it helps that I happen to have met the maintainer of attrs at PyCon (and attrs has only one uploader in PyPI), and therefore I'm less concerned about supply-chain attacks against it, whether of the malicious-maintainer variety or the maintaner-got-scammed-or-hacked variety, than, again, most of my other dependencies whose maintainers I've never heard of. I'm not sure this scales particularly well, but I do feel like there's still something in the open source community being a community.
- glyph 5y agoNot that attrs or dataclasses has particularly significant attack surface, but when considering stdlib vs. 3rd-party you also have to consider the amount of maintenance and the release cadence. Attrs can release every few months if the rate of change demands it, whereas the stdlib has a fixed yearly release schedule that is tied to interpreter versions. Attrs has a small, focused development team whereas the stdlib is maintained by developers who are stretched very thin, and many packages within it are effectively abandoned. Upgrading dataclasses means upgrading everything in the stdlib at the same time, whereas attrs can be upgraded independently, by itself. Supply chain attacks are a complex and nuanced topic so there are plenty of reasons to be thoughtful about adopting new dependencies, but it's definitely not as simple as "just use the stdlib for everything".
- nsonha 5y agoNot a python guy, so confused as to why a thing called namedtuple behaves like dataclasses, what are their different usecases?
- aix1 5y agoNamed tuples have been around for a long time (since 2.6), whereas dataclasses are a relatively recent addition to the standard library (3.7). Their differences are highlighted in the dataclasses PEP: https://www.python.org/dev/peps/pep-0557/#why-not-just-use-namedtuple https://www.python.org/dev/peps/pep-0557/#why-not-just-use-n...
- nsonha 5y agolooks like the key thing is immutability
- aix1 5y agoTo clarify, both named tuples and dataclasses can be immutable (the former are always immutable and the latter can be made immutable with `frozen=True`). There is no way, however, to make a named tuple mutable.
- dreamofkoholint 5y agoKey thing for me was the ability to add type hinting
- rguillebert 5y agoNamedtuples also behave like tuples, which is great when you want to incrementally turn tuples into classes but if you want an easy way of creating classes, it's probably not a good idea to have them behave like tuples. Plus dataclasses have more features.
- pletnes 5y agoThere’s also the fact that sometimes you need an actual tuple - in some places (C extensions like numpy, opencv, …) and a dataclass just doesn’t work.
- ahurmazda 5y agodataclasses also have the slots kwargs since 3.10. Should help with faster access and memory
- samplenoise 5y agoRaymond Hettinger’s (perhaps biased) take on dataclasses vs attrs: https://m.youtube.com/watch?v=T-TwcmT6Rcw https://m.youtube.com/watch?v=T-TwcmT6Rcw
- greymalik 5y agoattrs is a superset of dataclasses.
- EdSchouten 5y agomy_point3d = (1.0, 2.5, 7.2) Voila!
- skrtskrt 5y agoIMO Pydantic is way more ergonomic, has great defaults, and easier to bend to your will when you want to use it a little differently. Lots of love to Attrs, which is a great library and is a component of a lot of great software. It was my go-to library for years before Pydantic matured, but I think a lot of people have rightly started to move on to Pydantic, particularly with the popularity of FastAPI
- kaashif 5y agoPydantic is dataclasses, except types are validated at runtime? It's nice and looks just like a normal dataclass looking at https://pydantic-docs.helpmanual.io/ https://pydantic-docs.helpmanual.io/ For any larger program, pervasive type annotations and "compile" time checking with mypy is a really good idea though, which somewhat lessens the need for runtime checking.
- skrtskrt 5y agoPydantic types will be checked by mypy or any other static type analysis tool as well. I don’t expect any type-related thing to be remotely safe in Python without applying at least mypy and pylint, potentially pyright as well, plus, as always with an interpreted language, unit tests for typing issues that would be caught by a compiler in another language
- skrtskrt 5y agoWelp not sure why I caught downvotes for using the two most common static analysis tools for Python, but here we are on Hacker News
- joshuamorton 5y agoLikely the reason is that you really only need just mypy. It handles the type issues. Pylint is useful, but doesn't really overlap with mypy in terms of what it catches, and there's no need to use pyright or to write type-verifying unit tests, or to do runtime type validation if you have mypy. Using mypy gives you the type safety equivalent of a compiled language. If you're using mypy, you don't need any additional validation that you wouldn't use in java or c++. I didn't downvote you, but the needless defense in depth is weird.
- flohofwoe 5y ago...or one could just use Python without classes, just functions. TBH I never quite understood why Python has the class keyword, it's a much better language without.
- ledauphin 5y agoattrs really isnt about OO-style classes - it's specifically meant to provide struct-like declarative data containers, and these can help bridge the gap between the toolset that Python provides and functional (data-first) programming styles.
- rthomas6 5y agoI thought like you for several years. Then one day, I needed a custom type. You can use dicts (or lists, or namedtuples, I guess?), but it just ends up being cleaner and more idiomatic to define a class for the type, because you can define common methods for them. The article mentions quaternions. If you make a quaternion type (class), you can define addition, multiplication, comparison, etc. for it (methods). If you represent a quaternion any other way, you can't say a * b. Or maybe you can, but I don't know how.
- lvass 5y agoYou can represent it as whatever and monkey patch it's __mul__. It's a bit complicated with standard library structures that may be implemented in C, though.
- Starlevel001 5y agoThis is an obvious troll post but python is a pure OO language, everything is a an object with an associated class. Functions are just instances of FunctionType.
- willseth 5y agoSomeone should tell this person about dataclasses
- deleted 5y ago[deleted]
- nhumrich 5y agoI mean, the blog post is older than dataclasses
- willseth 5y agoGreat, maybe OP shouldn’t post and people shouldn’t upvote outdated blog posts with bad advice
- geofft 5y agodataclasses was explicitly inspired by attrs. https://github.com/ericvsmith/dataclasses/issues/1 https://github.com/ericvsmith/dataclasses/issues/1
- willseth 5y agoThank you for reinforcing my point
- shakna 5y agoAttrs was mentioned in the PEP [0] for dataclasses. [0] https://www.python.org/dev/peps/pep-0557/#why-not-just-use-attrs https://www.python.org/dev/peps/pep-0557/#why-not-just-use-a...
- willseth 5y agoExactly
- 4ec0755f5522 5y agoI started a project with dataclasses and quickly ran into their limitations (which are by design) and migrated to attrs. It's quite a bit better. If you take 10 seconds to read attrs website they do go over the differences and maybe discussing those would be more valuable than some cheap snark.
- bjourne 5y agoCosts: Depending on a relatively unknown library. Using arcane class decorators and unusual syntactic constructs: @attr.s and x = attr.ib() (a pun?). Benefits: Saving at best 10-15 lines of boilerplate per data class. Much less if namedtuple works for you. If you want to save lines in __init__ you can write "for k, v in locals().items(): setattr(self, k, v)". But you shouldn't. Edit: Forgot to add to the most important cost: Magic. You don't need to know a lot of Python to understand how the standard self.x = x initialization works. However, you do need to understand a lot of Python internals to grok x = attr.ib().
- ledauphin 5y agothere are newer (since 2020) syntactic constructs that might be more to your liking. take a look at the docs again. Incidentally, I'd recommend against Named Tuples for non-trivial software. Because they can be indexed by integer and unpacked like tuples, additions of new fields are backwards-incompatible with existing code.
- atorodius 5y agoyeah this has bitten me before. combine it with overwriting len for a namedtuple and you have a proper mess
- bjourne 5y agoI don't like newfangled syntactic constructs since they hide what is going on. :) The example in the article was a Point3D class and for that namedtuple is a good choice (points should be immutable). It's unlikely that you'd want to add fields without also making other backwards-incompatible changes.
- dragonwriter 5y ago> Depending on a relatively unknown library attrs is not “relatively unknown” as Python libraries go. > Using arcane class decorators and unusual syntactic constructs: @attr.s and x = attr.ib() (a pun?). There have been conventional, SFW aliases for the punny ones for...a long time.
- 5y ago
- jpalomaki 5y agoThis is from 2016.
- danbmil99 5y agoWhy is Attrs incorrectly capitalized in the headline? Is that an automatic feature of the software?
- unbanned 5y agoErm. Pydantic. Or dataclasses.
- NeutralForest 5y agoFor anyone interested in differences between attrs and pydantic, how to use dataclasses, etc. I can't recommend the mCoding channel enough, this video : https://www.youtube.com/watch?v=vCLetdhswMg https://www.youtube.com/watch?v=vCLetdhswMg goes into the different libraries and there are other videos going more in depth on how to use them.
- nauticacom 5y agoI've never understood the appeal of these "define struct-like-object" libraries (in any language; I've never understood using the standard library's "Struct" in Ruby). My preferred solution for addressing complexity is also to decompose the codebase into small, understandable, single-purpose objects, but so few of them end up being simple value objects like Point3D. Total ordering and value equality make sense for value objects but not much else, so it really doesn't improve understandability or maintenance that much. And concerns like validation I would never want to put in a library for object construction. In web forms where there are a limited subset of rules I always want to treat the same way, sure, but objects have much more complicated relationships with their dependencies that I don't see much value in validating them with libraries. Overall, I really don't see the appeal. It makes the already simple cases simpler (was that Point3D implementation really that bad?) and does nothing for the more complicated cases which make up the majority of object relationships.
- atorodius 5y agowell one appeal is that you dont have to write constructors, that‘s already enough of a win for me. then you get sane eq, and sane str, and already you remove 90% boilerplate
- nauticacom 5y agoI really, genuinely don't get the appeal. I don't follow the "less code = better" ideology so maybe that's a contributor but I really don't see how this: class Person: def __init__(self, name, age): self.name = name self.age = age is any worse than this: @dataclass class Person: name: str age: int I'm not writing an eq method or a repr method in most cases, so it just doesn't add much for the cost.
- michaelcampbell 5y agoGiven that code is for people, I've never found a certain amount of idiomatic boilerplate a problem. The desire to remove it all, or magicify it away (eg: Django) has always made me do a bit of an internal eye roll.
- atorodius 5y agoThis is only remotely relevant but I recently learned that the related `dataclasses` is implemented by constructing _string representations_ of functions and calling `exec` on them. https://github.com/python/cpython/blob/3.10/Lib/dataclasses.py#L529 https://github.com/python/cpython/blob/3.10/Lib/dataclasses.... Kind of blew my mind
- bjourne 5y agoEw. How can there not be some better way to do it?
- keithalewis 5y agoNew to python? It might be big, but it sure is slow!
- Spivak 5y agoYou should look at the older implementation. The whole class itself was made by interpolating a huge string and the exec-ing it but was changed with the ability to dynamically generate classes with type(). Nothing other than motivation and a good proposal is standing in the way of a def() that operates similarly.
- posix86 5y agolog4j v2 incoming...
- dang 5y agoPast related threads: Attrs – The python library everyone needs (2016) - https://news.ycombinator.com/item?id=17160262 https://news.ycombinator.com/item?id=17160262 - May 2018 (2 comments) Using attrs for everything in Python - https://news.ycombinator.com/item?id=12359522 https://news.ycombinator.com/item?id=12359522 - Aug 2016 (101 comments) The One Python Library Everyone Needs - https://news.ycombinator.com/item?id=12285342 https://news.ycombinator.com/item?id=12285342 - Aug 2016 (1 comment)
- tddispointless 5y agoI used attrs in a large python project, and it was more pain than it was worth. Off the top of my head, knowing the difference between factory vs default in the initializer was a bug that bit us, inheritance was painful because we were forced to redefine the attrs from the parent class in each child class (maybe they fixed this now). Validators were broken somehow. I even made a GitHub issue for this which was never addressed. Attrs are good for simple stuff. I feel plain old classes are more reliable once things get complex. And for simple things, dataclasses do just fine too.
- Lamad123 5y agoThis forcefully casual style of writing wouldn't have an introduction but it wouldn't get to the point in the first couple paragraphs either.
- divbzero 5y agoThe @dataclass decorator [1] as proposed in PEP 557 [2] has also been available since Python 3.7 was released in 2018. Using @dataclass the example from OP would look like: from dataclasses import dataclass @dataclass class Point3D: x: float y: float z: float [1]: https://docs.python.org/3/library/dataclasses.html https://docs.python.org/3/library/dataclasses.html [2]: https://www.python.org/dev/peps/pep-0557/ https://www.python.org/dev/peps/pep-0557/
- hamstergene 5y agoAs soon as I opened the article I pressed Cmd+F and searched for "dataclasses". This article was correct and addressed a very real need in Python programming—for year 2016. By now it is obsolete and today's standard library module `dataclasses` does all of that and more.
- ttwwmm 5y agoattrs classes still have several features that dataclasses don't, and likely never will, [like validators and converters](https://www.attrs.org/en/stable/why.html#data-classes https://www.attrs.org/en/stable/why.html#data-classes). So it's not obsolete, particularly for anyone already relying on those features.
- nurettin 5y agodataclasses have methods for iterating fields and inspecting types, so any feature can be added. There is also the benefit of type checking. My grief with dataclasses is how I can't inherit from dataclasses with default fields without making all child class fields also have defaults.
- ericvsmith 5y agodataclasses author here. Does the keyword-only feature in 3.10 help you at all?
- harpiaharpyja 5y agoI think the author is overselling this library. A lot of the problems they mention can be avoided with a consistent application of discipline. You can decompose classes that become too big for their own good. You can design your software, layer abstractions intelligently etc. so that having to do such refactoring isn't a big issue. Python is a language that demands an above average level of discipline compared to many other programming languages I have used, but only because it IMO leans strongly towards empowering the developer instead of restricting them.
- entelechy0 5y agoAgreed. There was some drama with twisted years ago involving python 2-3 interoperability iirc. The title reads like clickbait and having to hook me on an article this way only serves to repulse me physically.
- frenchie4111 5y agoPlease look at Pydantic if you are interested in attrs or dataclasses. For a bunch of reasons it’s better (happy to discuss if anyone wants)
- amirkdv 5y agoThere's good discussion in this thread about when and why to use attrs, pydantic, or stdlib dataclasses; I have my own thoughts too. But all I can really feel is gratitude for all of us not having to do namedtuple/slot contortions anymore. Good riddance.
- julienfr112 5y agoI'm writing python code that is not OOP at all, mostly functional (list and dict comprehension, pure function) and use only list, dict, set and combination of them. Am I alone ?
- mindv0rtex 5y agoMy favourite among this class of Python libraries has been traits from Enthought: https://github.com/enthought/traits https://github.com/enthought/traits