7

Suppose there is a class with a @property defined:

class MyClass:
   ...
   @property
   def this_is_a_property(self):
       return self.some_thing
   ...
   def this_is_a_function(self, x):
       ...
       return other_thing

Normally, to check whether an attribute is a function, I can use isfunction from the inspect module.

 import inspect
 if inspect.isfunction(MyClass.__dict__['this_is_a_function']):
    print('this_is_a_function',' is a function')

How can I check a property? There appears to be no inspect.isproperty function.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
uday
  • 6,453
  • 13
  • 56
  • 94

2 Answers2

8

Simply check the type against the property object:

if isinstance(MyClass.this_is_a_property, property):

You don't really have to retrieve it from the class dictionary here; looking up a property on the class as an attribute also returns the property instance.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
3

You could use inspect.isdatadescriptor:

Return true if the object is a data descriptor. ... Examples are properties (defined in Python), getsets, and members.

...

CPython implementation detail: getsets are attributes defined in extension modules via PyGetSetDef structures.

...

CPython implementation detail: Member descriptors are attributes defined in extension modules via PyMemberDef structures

Data descriptors are just types that have certain methods. See 3.3.2.1. Implementing Descriptors:

If the descriptor defines __set__() and/or __delete__(), it is a data descriptor; if it defines neither, it is a non-data descriptor.

Non-data descriptors include classmethod and staticmethod (that is, they're not functions, they're types). For example, inspect.isdatadescriptor(MyClass.this_is_a_classmethod) would return False.

On the other hand, property is a data descriptor:

In [6]: inspect.isdatadescriptor(MyClass.this_is_a_property)
Out[6]: True

The downside of using this function is that it may return True if isinstance(mystery, property) is False.

A better way is to check for object type directly:

In [7]: isinstance(MyClass.this_is_a_property, property)
Out[7]: True
vaultah
  • 44,105
  • 12
  • 114
  • 143