0

Is there a way to determine a class attribute is a Property (with __get__ and __set__ or not? The method in Determine if given class attribute is a property or not, Python object looks like only work for property decorator, which is not work in my case.

class Property(object):
    _value = None
    def __get__(self, instance, owner):
        return self._value 
    def __set__(self, instance, value):
        self._value = value * 2


class A(object):
    b = Property()

>>> a = A()
>>> type(A.p)
<type 'NoneType'>
>>> type(a.p)
<type 'NoneType'>
Community
  • 1
  • 1
lucemia
  • 6,349
  • 5
  • 42
  • 75

1 Answers1

1

Your descriptor returns None because it is also invoked for classes (the instance attribute is set to None when __get__ is called for that scenario).

You need to retrieve it without invoking the descriptor protocol, reaching into the class __dict__ attribute is the most direct path:

A.__dict__['p']

See the Python Descriptor HOWTO for more details on how and when descriptors are invoked.

Alternatively, do as the property object does and return self when instance is set to None (so when accessed on a class):

class Property(object):
    _value = None
    def __get__(self, instance, owner):
        if instance is None:
            return self
        return self._value 
    def __set__(self, instance, value):
        self._value = value * 2

Also see How does the @property decorator work?

Demo:

>>> class Property(object):
...     def __get__(self, instance, owner):
...         return self._value 
...     def __set__(self, instance, value):
...         self._value = value * 2
... 
>>> class A(object):
...     b = Property()
... 
>>> A.__dict__['b']
<__main__.Property object at 0x103097910>
>>> type(A.__dict__['b'])
<class '__main__.Property'>
>>> class Property(object):
...     _value = None
...     def __get__(self, instance, owner):
...         if instance is None:
...             return self
...         return self._value 
...     def __set__(self, instance, value):
...         self._value = value * 2
... 
>>> class A(object):
...     b = Property()
... 
>>> A.b
<__main__.Property object at 0x10413d810>
Community
  • 1
  • 1
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343