Live data from Hacker News

Using attrs for everything in Python

glyph.twistedmatrix.com

31–40 of 105 posts

Re: Using attrs for everything in Python

#31

It feels a bit hampered by "bad" design decisions to me I think its safe to say that the current view of what decorators do is, a) filter things going to functions (so they error, or hit a cache), or b) register a function with another library (e.g. flask path decorator) This library does a lot more than that, so it seems that maybe a metaclass (which exists to mutate the class's creation) would be more appropriate?…

Agreed.

From the post, it seems to me like another (IMO better) alternative to this awkward attr-specific convention and syntax etc would be to create a factory function for dynamic class definition, in a similar vein to namedtuples.

This is functionally similar to the metaclass route, and to be honest I'm not sure what the tradeoffs would be. Either way, I think metaprogramming is a much better approach than attrs if the problem you're trying to solve is "generic container classes take too long to get set up".

I think, were I to write something like this, I would probably do it using a metaclass, and then inject an __init__ on the MRO between the programmer-defined __init__ and the actual super().__init__. That way, you could call super().__init__(arg1, arg2, arg3) for the automatic attribute setting. You could also hook this in to some metaclass-defined storage containers to automate the __repr__ implementation, etc.

Re: Using attrs for everything in Python

#32

Earlier quoted context omitted.

You'd have to expand more on your proposal for using a dictionary for people to be able to reply. The article was full of use cases, so why not address those rather than simply state that you can't think of any? When you say use a dictionary, do you mean subclass `dict`? One of the aims of the project is to constrain the available instance attributes, as in a normal class. How would your dict proposal do that?

In that case, I'd just deal with the overhead of a normal class. More boilerplate, of course, but I'd have more control over the class. As to the use cases, I was not really buying into them other than the nice destructuring example, which is actually very nice one.

I think the point is that this is basically a normal class, but one with the boilerplate already written for you. If you don't mind boilerplate, this library does nothing for you. If you don't want to write classes and think dicts are good enough, this library does nothing for you.

If you do want to have classes but don't want the boilerplate that comes with making a basic-but-full-featured class, then that's where this library comes in.

Re: Using attrs for everything in Python

#33

It feels a bit hampered by "bad" design decisions to me I think its safe to say that the current view of what decorators do is, a) filter things going to functions (so they error, or hit a cache), or b) register a function with another library (e.g. flask path decorator) This library does a lot more than that, so it seems that maybe a metaclass (which exists to mutate the class's creation) would be more appropriate?…

[deleted]

Re: Using attrs for everything in Python

#34

It feels a bit hampered by "bad" design decisions to me I think its safe to say that the current view of what decorators do is, a) filter things going to functions (so they error, or hit a cache), or b) register a function with another library (e.g. flask path decorator) This library does a lot more than that, so it seems that maybe a metaclass (which exists to mutate the class's creation) would be more appropriate?…

>I think its safe to say that the current view of what decorators do is, a) filter things going to functions (so they error, or hit a cache), or b) register a function with another library (e.g. flask path decorator)

Why is it safe to say that? Aren't decorators just syntax for higher-order functions?

Re: Using attrs for everything in Python

#35

It feels a bit hampered by "bad" design decisions to me I think its safe to say that the current view of what decorators do is, a) filter things going to functions (so they error, or hit a cache), or b) register a function with another library (e.g. flask path decorator) This library does a lot more than that, so it seems that maybe a metaclass (which exists to mutate the class's creation) would be more appropriate?…

Your view of what decorators doesn't seem to reflect the usage I've experienced writing Python professionally over the last 10 years.

Decorators take an object and return a object (by convention a callable, although this isn't enforced in the slightest). Maybe they modify a function or method signature, maybe it produces an unrelated object, or maybe one augments the object by adding side effects like caching or logging.

There is a special syntax (@) legal for classes, functions, and methods that provides a shortcut for the common pattern of:

    def decorator(): ...
    def foo(): ...
    foo = decorator(foo)
such that we can say:

    @decorator
    def foo(): ...
Things I've seen decorators do:

    * add logging
    * add tracing
    * enable type validation
    * register functions/objects for various reasons
    * produce full objects out of functions
    * swap out implementations for global functions/vars
    * change output formats to json/xml/yaml
    * take a class, inspect a database schema and bind various internal attributes to update items in a row for that schema (somewhat common in ORMs)
I don't see this attrs library as any more egregious than other uses. In particular, I don't see why mutating a type via a metaclass is preferable to using a decorator. I can offer that decorators generating objects compose much better than metaclasses do (at least they have in python 2.x, I haven't had a chance to use 3 professionally).

Re: Using attrs for everything in Python

#36
I can't find it at the moment but wasn't there another solution to this problem where you could just populate an object at will (like matlab's struct for instance)? IIRC it was dict-based and allowed something like

    foo = SomePythonWizardry()
    foo.x = 1
    foo.a.b = 2
    print( foo ) #yields e.g. foo.x = 1, foo.a.b = 2
Or am I just dreaming? It would be all the goodness and none of the weird syntax.

Re: Using attrs for everything in Python

#37
post #36

I can't find it at the moment but wasn't there another solution to this problem where you could just populate an object at will (like matlab's struct for instance)? IIRC it was dict-based and allowed something like foo = SomePythonWizardry() foo.x = 1 foo.a.b = 2 print( foo ) #yields e.g. foo.x = 1, foo.a.b = 2 Or am I just dreaming? It would be all the goodness and none of the weird syntax.

You're probably thinking of jsobject¹:

    from jsobject import Object
    foo = Object()
    foo.x = 1
    foo.a = {}  # foo.a.b will fail without this line
    foo.a.b = 2
    print(foo)  # prints: {'a': {'b': 2}, 'x': 1}
¹ https://pypi.python.org/pypi/jsobject/

Re: Using attrs for everything in Python

#38

How does this compare to schematics? It avoids inheritance, whereas in schematics and similar projects you'd have to inherit from their `Model` class (and thus acquire methods you might not want).

Schematics looks a bit like a less elegant version of schema. It does seem more focused on validation than attrs, I agree.

Re: Using attrs for everything in Python

#39

The problem with constructs like this one is that it looks nice at first glance, but adds a cognitive load to an ecosystem that already has about "20 ways to do it" for every single problem. Python is beginning to rival C++ in that respect.

Please don't tell the C++ community that! We really don't want to encourage them.

To someone who uses Python every day, the extra cognitive load of `attr` is more than made up for by all the boilerplate it eliminates. But for beginners, behind-the-scenes magic is a real turn off.

I think that making `attr` an optional library is a fair compromise, but perhaps it would be a good idea to add a note to the library reminding the programmer not to use it if the code is likely end up in the hands of novices.

Re: Using attrs for everything in Python

#40
In the end, this is about defining a typed structure. "@attr" plus validator constraints is effectively a typed structure.

Python got further with minimal declarations than any other mainstream language. Yet there's a demand for typed variables. This is going into future Python, although in a strange and clunky way, because types don't fit the syntax.

We seem to be converging on a consensus on when to declare types. The breakthrough was "auto", in C/C++, which declares a variable as the type of the value to which it is initialized. This is the default in Go and Rust. Function formal parameters and structure slots have explicit type declarations, while local variables are usually implicitly typed.

Python seems to be moving in this direction, but from the no-type-declarations direction. Unfortunately, because the language itself doesn't do this well, it's being kludged through decorator macros.

Post reply on HN