Experiment: Replace __setattr__ With A Descriptor
As part of daily life I see a ton of Python code. Between the code at work and all of the open source projects I watch I’m surprised my eyes don’t bleed. Over the years my style has changed dramatically. I guess you could say I am getting more Pythonic. Looking back at old code sometimes just make me feel ill. I know better now.
There was a project that I worked on where we wanted to ensure all attributes were typed properly. (No comments about this - it’s not the point of the post) To do this we used an evil combination of Hungarian notation and setattr magic. An example class looks something like this:
class Data(object):
def __init__(self, strX='', fltY=0.0, intZ=0):
self.strX = strX
self.fltY = fltY
self.intZ = intZ
def __setattr__(self, name, value):
if name.startswith('int'):
object.__setattr__(self, name, int(value))
elif name.startswith('flt'):
object.__setattr__(self, name, float(value))
elif name.startswith('str'):
object.__setattr__(self, name, str(value))
else:
object.__setattr__(self, name, value)
As ugly as it is it actually works. All attributes are forced to a type based off of their name. I know the setattr is rather slow, but I never really gave it a second thought even thought I periodically see this code. This weekend a neuron misfired and I had an idea. So I gave this a whirl:
class TypedAttr(object):
def __init__(self, _type, value):
self._type = _type
self._default = self._value = value
def __get__(self, obj, _type):
return self._value
def __set__(self, obj, value):
self._value = self._type(value)
def __delete__(self, obj):
self._value = self._default
class Data(object):
strX = TypedAttr(str, '')
fltY = TypedAttr(float, 0.0)
intZ = TypedAttr(int, 0)
This Data class is must cleaner. The TypedAttr can be defined in another module making this code much smaller and more declarative.
The descriptor approach out performs the getattr. My tests were using the timeit module in Python 2.5. Running the old way gave me about 25 usec and the new way was 11 usec.
I think I’ll suggest the change
Comments
-
dstanek
-
Ralph Heimburger
-
dstanek
-
Tom Lynn
-
dstanek
-
dstanek
-
Peter Otten
-
Robert Brewer
-
Doug Napoleone
-
Michael Watkins
-
Mike Pirnat








