[Nipy-devel] help with attributes
Brian Hawthorne
brian.lee.hawthorne at gmail.com
Thu May 18 00:29:32 CDT 2006
Hi Jonathan (and list),
p.s. does attribute offer the same thing traits does? if yes, should we
> be using both? i am kind of used to traits by now...
I've been planning to broach this subject on list for a while, but you beat
me to it!
(What follows is rather long, but I'm hoping to generate some discussion.)
The attribute system does offer roughly the same sort of functionality that
traits provide. Should we be using both? Definitely not in the long term,
though they can certainly coexist in the codebase (not on the same class)
for however long is necessary. My hope is that we can migrate to attributes
and that everyone will agree that's a good idea. :) Here's what I'm
thinking:
Traits was written before properties were added to python, as a way to
formally declare object attributes, enforce typing, and trap attribute
access events. Properties take care of the formal declaration and the
access trapping; so given that alone, I would consider two thirds of traits'
functionality obsolete already. Also, traits requires the host class to
inherit from HasTraits, potentially screwing with your inheritance
hierarchy, and definitely messing with your metaclass. In addition,
HasTraits adds a huge number of attributes and methods to the host class
(aka "bloat"), making autogenerated documentation a morass. In addition,
standard python documentation generators (pydoc, epydoc) know how to play
nice with properties, but generate meaningless drivel when presented with
traits, requiring the use of enthought's own special documentation tool
(another dependency -- yuck!).
On the other hand, properties are annoying sometimes too: no type checking,
the getter and setter funcs must be defined separately and then passed to a
property constructor (unless you're using lambdas, but those can't be very
big, plus they're ugly), properties don't know their own names, and you
can't access the property object itself in the getters/setters. This is
where attributes come in. Attributes are more pythonic than traits because
they are properties, and as such are more "standard" than traits (eg,
standard doc tools know what to do with them). Attributes are more
strategically implemented because they leverage properties instead of
reimplementing the functionality that properties provide. In addition, as
properties, attributes don't require the host class to inherit from anything
special. Attributes are more portable as well because they are implemented
in pure python with no C code (as traits has). Attributes overcome the
separation of the components of a property declaration by providing a nested
code block (inside the host class definition) under which the getters and
setters etc. may be defined. This allows the entire attribute declaration
to be performed in a single python statement, regardless of how
sophisticated it might be. Needless to say, attributes know their own
names, and getters/setters receive a reference to the attribute object
itself in addition to the host class instance. As far as typing goes,
attributes can be declared to implement a protocol, rather than being
restricted to a particular type, making them again more pythonic by
embracing "duck typing" (if it walks like a...). Another useful feature
which I'm not sure if traits implements or not is a simple access control
mechanism (private vs public). An attribute whose name begins with an
underscore can only be referred to inside a method of its host class. One
final feature is dirt simple delegation, for when you need
some inheritance-like behaviour in an object graph instead of a class tree.
When I sat down with Matthew Brett a few weeks ago to start diggin in the
code, the very first thing we wanted to do was make a read-only trait
(actually set-once, then read-only). It must be easy... but after skimming
the documentation for 10 minutes, we still didn't know how to do that! We
did find a trait called ReadOnly, but it was a red herring (behaved more
like a constant). So that was the initial impetus to implement attributes.
That leads to another discussion I'd like to have soon: copy vs modify.
I'll save that for another posting though ;)
The attributes module's main docstring contains a doctest which serves as a
mini-tutorial:
http://projects.scipy.org/neuroimaging/ni/browser/ni/trunk/lib/attributes.py
If you've read this far then hopefully you have an opinion; I'd like to hear
it!
(traits vs attributes line count is below.)
Cheers,
Brian
In the traits-1.0.2 source dir:
% wc -l $(find enthought/traits/ -name "*[.py,.c]")
13292 total
In the nipy main project dir:
% wc -l lib/protocols.py lib/attributes.py
401 total
A whopping 97% code reduction!
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://projects.scipy.org/pipermail/nipy-devel/attachments/20060517/af843722/attachment.html
More information about the Nipy-devel
mailing list