Some folks, presented with the attr.s API, make the entirely reasonable inference that this:
@attr.s
class Foo:
_bar = attr.ib()
is a class you should use like this:
This is further exacerbated by the fact that Foo's repr actually shows you exactly that string.
The only example in the docs that I can find is the code example at the bottom of the attr.s API doc.
This behavior should be thoroughly documented and explained, and, um, maybe tweaked a little bit, since there are some issues with it. As it stands now, for example, there's no publicly-named attribute for API doc generation tools, or code-completion things, to pick up to present as the constructor argument.
If I could take a stab at the rationale for this behavior, it's something like this:
In Python, if you have a function with "private" arguments, they all have positional names, which makes them effectively public. Therefore, there is no point in trying to "hide" your constructor arguments behind _ prefixes, since a user might happily do Foo(1) and never realize that they've done something unsupported. Therefore attr.s always makes the keyword-arg names of your constructor arguments "public" by removing their underscores; the attributes themselves are of course private and can still have the _ prefix when accessed as self._something.
Except, in Python 3, this isn't true any more, because the advent of keyword-only arguments means you can't pass the argument without actually having to type in an _ in a namespace you don't own, which means it's totally valid to have internal "don't pass me this in the constructor" state. IMHO this is great - it's a way to force public users through a class-method constructor or factory function without hiding the type itself (and all the methods on it) or resorting to any gross shenanigans to make the constructor literally private. So it turns out I really would like "private attributes" that don't show up in the constructor either! (And of course, at the metaprogramming level where Attrs itself lives, the kwarg-only behavior can be emulated on python 2.)
Some folks, presented with the
attr.sAPI, make the entirely reasonable inference that this:is a class you should use like this:
This is further exacerbated by the fact that
Foo'srepractually shows you exactly that string.The only example in the docs that I can find is the code example at the bottom of the
attr.sAPI doc.This behavior should be thoroughly documented and explained, and, um, maybe tweaked a little bit, since there are some issues with it. As it stands now, for example, there's no publicly-named attribute for API doc generation tools, or code-completion things, to pick up to present as the constructor argument.
If I could take a stab at the rationale for this behavior, it's something like this:
Except, in Python 3, this isn't true any more, because the advent of keyword-only arguments means you can't pass the argument without actually having to type in an
_in a namespace you don't own, which means it's totally valid to have internal "don't pass me this in the constructor" state. IMHO this is great - it's a way to force public users through a class-method constructor or factory function without hiding the type itself (and all the methods on it) or resorting to any gross shenanigans to make the constructor literally private. So it turns out I really would like "private attributes" that don't show up in the constructor either! (And of course, at the metaprogramming level where Attrs itself lives, the kwarg-only behavior can be emulated on python 2.)