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
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