I like python, but I’ve wasted too much time writing boilerplate code for objects. I like the look of attr. I need to take it for a spin!


Lefkowitz: The One Python Library Everyone Needs [LWN.net]

David Megginson August 14, 2016 07:37

Tempting, but I’m not convinced yet — it looks a bit like a crutch for someone coming from a language like Java, where everything has to be a class. When there are no complex, encapsulated actions that need to be associated with a data structure, I suspect it’s more Pythonic just to use a dict.

Michael K Johnson August 14, 2016 07:51

Hmm. “has to be” vs. avoiding boilerplate when writing classes. And there is nothing that says that this is useless when writing classes that have”complex, encapsulated actions”—it is just that the examples keep things simple.

I find my code easier to reason about when I’m not using dicts of lists of dicts of tuples of dicts of lists of …

It’s also easier to write useful tests-as-documentation with semantic data types.

And [‘…’][0][‘…’] is not easier to understand than foo.bar.baz; I don’t agree with the assertion that it’s more pythonic.

My point is that I do, in practice, when writing Python code, especially with tests (almost always), write the boilerplate code that this would get rid of. In practice, it is not perfectly consistent, and sometimes I add bugs in the boilerplate…

I don’t find specific objects a “crutch”. I find that they make my code more explicit, and what is more pythonic than “explicit is better than implicit”?

David Megginson August 14, 2016 08:02

I forgot to thank you for sharing this, Michael. I hadn’t been aware of the library before. I was thinking more of myself when I wrote “crutch,” since I tend still to think in classes — I learned Java in my 30s, when I was still at an impressionable age (and C++ even earlier).

The biggest saving I see here is not having to write the constructors (I’m surprised how rarely I need to test objects for equality). However, if a constructor does nothing but set attributes, I have to ask myself whether I’m really looking at something that should be a class.

The biggest drawback, though, is maintainability. Will the next person to look at this code understand what it’s doing, when it doesn’t look like typical Python? Will I still understand in 5 years? Will my (or someone else’s) present or future IDE be able to analyse and refactor the code? It seems like a lot of risk to take on for the sake of saving 5 minutes of typing out a standard, universally-understood class constructor.

Michael K Johnson August 14, 2016 12:03

I care less about setting attributes and more about dot notation to make the code more self-explaining, which is my main reason for small classes.

I use decorators quite a bit, especially in tests, and I think that any IDE that is confused by this pattern probably is going to be confused by decorated classes generally, wouldn’t you think? I would expect that decorated classes are sufficiently common that any IDE worth its salt would understand them.

But my IDE is vi, so my interest here is academic. ;-)

David Megginson August 14, 2016 13:26

My IDE is Emacs, but I can’t count on that being true for other users. I’m fine with decorators where they’re special purpose (e.g. Flask controllers) or where they’re so common that they’re almost part of the core language, but I’m always nervous sacrificing transparency to gain brevity. I do agree that foo.bar.hack is more convenient to type than foo[‘bar’][‘hack’] — it’s too bad Python doesn’t allow the former as an alternate syntax for dicts, like JavaScript does.

Most of the time, though, I use actual classes, because I have more complex behaviour to encapsulate — in those cases, I don’t see saving more than a couple of lines, since I have to write a custom constructor anyway.

David Megginson August 14, 2016 13:27

If this did end up on track to become a standard Python feature, though, it would be great — in that case, I could count on it being readily comprehensible to other devs.

Michael K Johnson August 14, 2016 15:39

I don’t know how many times I’ve written a “ddict” (dotted dict) class that descends from dict and has a _getattr_ that lets me foo.bar.hack in my code…

I find a few well-named decorators useful to convey intended semantics because I can know at least what it is supposed to do more quickly than I can infer it from reading through more verbose code.

Frameworks seem to require that you understand a lot to read the code, though. Some months ago I was working in Pyramid and there was clearly an easy way to do almost anything; all you had to do was know all the details of the framework, whereas my goal was to finish one bit of work and then go away to other things that didn’t involve web frameworks, so investing in framework expertise was hard to justify. That definitely illustrates how heavily-decorated and heavily-subclassed code can become opaque to the casual developer.

Imported from Google+ — content and formatting may not be reliable