Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #19115

Python Descriptor as Instance Attribute

Date 2012-01-19 13:55 +0800
Subject Python Descriptor as Instance Attribute
From Hua Yanghao <huayanghao@gmail.com>
Newsgroups comp.lang.python
Message-ID <mailman.4851.1326952524.27778.python-list@python.org> (permalink)

Show all headers | View raw


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

Back to comp.lang.python | Previous | Next | Find similar | Unroll thread


Thread

Python Descriptor as Instance Attribute Hua Yanghao <huayanghao@gmail.com> - 2012-01-19 13:55 +0800

csiph-web