Python Descriptor as Instance Attribute

H

Hua Yanghao

Hi all,
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,
class Dummy(object):
d = DescriptorTest()

class Dummy2(object):
def __init__(self):
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[0] to bit[7] is
called M, bit[8] to bit[15]
is called N, and bit[16] to bit[31] is called Z.
I want to model a register that, when instantiated as "reg", reg.M/N/Z
can directly
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
different registers,
but that's not seems to be a very smart approach here, as I want all
register instances
be of type "Register". But the default python protocol will not run
descriptor protocols
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
__setattr__ and
__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
112
113 def __setattr__(self, name, value):
114 try:
115 obj = object.__getattribute__(self, name)
116 except AttributeError:
117 pass
118 else:
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
descriptors properly.

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,
Hua Yanghao
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top