4

Is there a way in Python 3.X to check if a class defines a setter method for one of its properties?

Let's say I have the following example :

class Test:
  def __init__(self):
    self._p = None

  @property
  def my_property(self):
    return self._p

  @my_property.setter
  def my_property(self, new_value):
    self._p = new_value

I can check if my_property is defined with hasattr but I can't find a way to check if the setter is defined.

Here are the two avenues I considered without success :

  1. Using hasattr to find if a method named my_property.setter or something like that exists.
  2. Using the inspect.signature function to see if the method my_property has 2 parameters (self and new_value).

I guess that an extended answer to this question would consider how to detect the presence of a getter as well (making the difference between a property and a getter method because callable(test.my_property) returns False when we might think it should be True because it is a method).

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
SpaceBurger
  • 537
  • 2
  • 12
  • What if the attribute is not a `property`? It's possible to set it but it doesn't have a `setter`. In that case, would you want the check to be positive (as if it has a setter) or negative? – Tomerikoo Oct 22 '20 at 09:55
  • 1
    Related: https://stackoverflow.com/questions/17330160/how-does-the-property-decorator-work-in-python (almost a duplicate as the answer is somewhere there in the accepted...) – Tomerikoo Oct 22 '20 at 10:02
  • 1
    "when we might think it should be True because it is a method)." – no, `test.my_property` is neither a method nor a property. `Test.my_property` is. – L3viathan Oct 22 '20 at 10:06

1 Answers1

3

You can test if the .fset attribute is None or not:

>>> Test.my_property.fset is not None  # has a setter
True
>>> Test.my_property.fdel is not None  # has no deleter
False

The same way you can also test if it has a getter (via .fget). To test whether the attribute is a property at all, you can test isinstance(Test.my_property, property).

Make sure to always call these on the class level, and not on an individual instance.

L3viathan
  • 26,748
  • 2
  • 58
  • 81