Python Descriptor as Instance Attribute
huayanghao at gmail.com
Thu Jan 19 00:55:21 EST 2012
Currently descriptors only work as class attribute,
and doesn't work as a descriptor when it is an instance attribute.
e.g. if we have descriptor class DescriptorTest,
d = DescriptorTest()
self.d = DescriptorTest()
The instance of Dummy2 does not invoke the descriptor protocols on "d".
Whereas Dummy() instances all share the same descriptor "d".
Yes I know d.__get__() have an "instance" parameter which can be used
to store per-instance values, but sometimes it is just not enough (or it is that
I do not know a better approach exists).
Suppose the below scenario, I want to model a "Register". A register is consist
of some fields, which have different number of bits.
e.g. a 32 bit register divided into 3 field, bit to bit is
called M, bit to bit
is called N, and bit to bit is called Z.
I want to model a register that, when instantiated as "reg", reg.M/N/Z
reference each field, calling a descriptor protocol to verify and
return the values.
Yes, I know I can use metaclass to create a different class for
but that's not seems to be a very smart approach here, as I want all
be of type "Register". But the default python protocol will not run
if a descriptor is an instance attribute. I'm sure I should not be the
only one that facing
this issue and I googled around and found a solution to redefine the
__getattribute__ to look up the descriptor protocols first:
107 def __getattribute__(self, name):
108 value = object.__getattribute__(self, name)
109 if hasattr(value, '__get__'):
110 value = value.__get__(self, self.__class__)
111 return value
113 def __setattr__(self, name, value):
115 obj = object.__getattribute__(self, name)
116 except AttributeError:
119 if hasattr(obj, '__set__'):
120 return obj.__set__(self, value)
121 return object.__setattr__(self, name, value)
This works like a charm and each instance of "Register" now invoke the
I just do not understand, why such behavior is not a default in python.
Or, is there a better design pattern here?
Thanks & Best Regards,
More information about the Python-list