Python Descriptor as Instance Attribute

Discussion in 'Python' started by Hua Yanghao, Jan 19, 2012.

  1. Hua Yanghao

    Hua Yanghao Guest

    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
    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
    Hua Yanghao, Jan 19, 2012
    1. Advertisements

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Donnal Walter

    class attribute to instance attribute

    Donnal Walter, Jun 30, 2005, in forum: Python
    Greg Ewing
    Jul 6, 2005
  2. Russell Warren
    Russell Warren
    Jan 17, 2006
  3. Eric Mahurin

    descriptor object for an attribute?

    Eric Mahurin, Apr 11, 2007, in forum: Python
    Eric Mahurin
    Apr 14, 2007
  4. Gabriel Genellina

    Re: get descriptor from instance

    Gabriel Genellina, Feb 18, 2009, in forum: Python
    Alan G Isaac
    Feb 19, 2009
  5. 陈伟
    Hans Mulder
    Aug 30, 2012

Share This Page