6 ms·
While the conciseness of attrs is nice, it's not very readable. This: class Point3D(object): def __init__(self, x, y, z): self.x = x
by mkolodny 10y ago
While the conciseness of attrs is nice, it's not very readable.
This:
class Point3D(object):
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
...is much easier to read than this:
import attr
@attr.s
class Point3D(object):
x = attr.ib()
y = attr.ib()
z = attr.ib()
Readability is what I love about Python. I don't think the conciseness of attrs is worth the loss in readability.
- dlbucci 10y agoAccording to the article, that's not really a fair comparison. The first example would need functools and at least 3 more methods to get to the same functionality of the latter example, at which point I think the former is less readable. That said, I'm not a big fan of wrapping classes, or this library's weirdly-but-concisely-named functions. I guess I'll have to give this a try the next time I'm writing Python to see if it's that much of a boost.
- crdoconnor 10y agoThose 3 methods aren't at all necessary for most objects you'll create and use.
- mixmastamyk 10y agoAlso, read the post and looked over the docs, and don't see any explanation of what `.s` and `.ib` is supposed to mean (though I can figure out from context). Does anyone know what the letters stand for? Struct and instance b…???
- hynek 10y agohttp://attrs.readthedocs.io/en/latest/overview.html#on-the-attr-s-and-attr-ib-names http://attrs.readthedocs.io/en/latest/overview.html#on-the-a...
- jfb 10y agoattr.s = "attrs" = plural of "attr" attr.ib = "attirb" = alternate spelling of "attr" It's too cute by half.
- ctoth 10y agoIt's awesome that Glyph wrote this article, but so many people are getting stuck on the default names here (me too, I don't like them so very much) that it's really detracting from the commentariet. From the Attrs documentation: (If you don’t like the playful attr.s and attr.ib, you can also use their no-nonsense aliases attr.attributes and attr.attr).
- Myrmornis 10y ago> They are a concise and highly readable way to write attrs and attrib with an explicit namespace. > For those who can’t swallow that API at all, attrs comes with serious business aliases: attr.attrs and attr.attrib. I'm definitely in the can't swallow camp. There's no precedent for using attribute namespaces to name things with half the name on one side and half the name on the other side, so who the hell does this project think it is to start doing it? :) Seriously though I'm pretty sure I hate it. And I'm having trouble liking the "proper" names. So we use a class decorator "@attrs" to declare "this class is going to use class attributes to declare available instance attributes slots, a bit like django or schematics fields". Maybe it would have been better to call it "@attrs.model" since it is essentially a model definition in the terminology of other data modeling projects?
- gknoy 10y agoIf you use `import ... as ...`, you can rename them to nicer names (full gist at [0]): from attr import ( s as AttributedModel, ib as attribute, ) @AttributedModel class Bar(object): x = attribute() y = attribute() 0: https://gist.github.com/gknoy/6e884fce3edda08a1566823fec37ba70 https://gist.github.com/gknoy/6e884fce3edda08a1566823fec37ba...
- scott_s 10y agoI find the @attr example more readable. I've been using Python for a while, but it's not my main development language. I mainly use it for scripting experiments, processing data and generating graphs. I generally avoid defining classes as much as possible, and use namedtuple whenever appropriate.
- rainy-day 10y agoAs I think others noted, the attr version does alot more: it adds representation and easily adds compare methods as shown in OP. Aside from that, this is not a fair comparison because attr names can, and mostly should be, longer, and there can be more of them, e.g.: class SomeClass(object): def __init__(self, myattr1, some_val, a_bool, my_other_attr): self.myattr1 = myattr1 self.some_val = some_val self.a_bool = a_bool self.my_other_attr = my_other_attr And of course they'll need to go into __str__ method as well.
- carapace 10y agoIt adds magic. "Explicit is better than implicit" ~https://en.wikipedia.org/wiki/Zen_of_Python https://en.wikipedia.org/wiki/Zen_of_Python
- deleted 10y ago[deleted]
- RubyPinch 10y agoI feel like a person should be able to back their opinion up (for a specific case, not in general), instead of just mindlessly quoting a line from a bible.
- dr_zoidberg 10y agoThen let's get rid of the with semantics too, because they add magic. Compare: with open("file.txt") as somefile: for line in somefile: print line To the more explicit and clear: somefile = open("file.txt") line = somefile.readline() while line: print line line = somefile.readline() somefile.close() But I'm still using some magic, I should be more explicit: def explicit_readline(fd): buff = [] char = fd.read(1) while char != "\n" and char != "": buff.append(char) return "".join(buff) somefile = open("file.txt", "rb") # just to be sure now line = explicit_readline(somefile) while line != "": # to be more explicit, of course print line line = explicit_readline(somefile) somefile.close() And we could go on like this to replace open with the os module file-descriptor functions, and print with sys.stdout/stderr (because more explicit, right?). But even without getting there, it should be obvious that: * The "explicit" verison no longer behaves as the original one, because, for example, explicit_readline only handles well the NIX newline character. If I want to provide the same functionality as file.readline() I should add a lot more code. I've reinvented the wheel for no good reason, and readability has suffered. It may also leave a lingering question in the mind of a read "why did he do that? is there some edge case that wasn't well documented anywhere and he bumped into?". * I've seen more contrived code do a version of this "more explicit" programming style, to the point of having statements like: def f1(number): number = int(number) return number & 0xff00 # or plug the number parameter in an equation, etc * ... (not a verbatim example, but along those lines). And that code is redundant and it will fail anyway if another thing other than an int/long/float is passed. It would be certainly saner to have an assert, or simply specify in the docs that said function expects a number (which is implied in the args too). My point was the "Explicit is better than implicit" means "be clear of your intent". And if I see someone using the attr module (which comes with the standard library), and I'm not familiar with it, I'll read into it. And for it's use case, I think it's clear enough in what it does, and how it should be used.