1

I am attempting to use property-based getters and setters in Python and am getting strange problems. Consider the following code:#!/usr/bin/env python

class anyThing(object):
    def __init__(self):
        self._xyz = 'something'

    @property
    def XYZ(self):
        return self._xyz
 
    @XYZ.setter
    def XYZ(self, value):
        self._xyz = value

t = anyThing()  # Construct an instance
print(f'Type of t.XYZ is {type(t.XYZ)}')
print(f'Invoking getter {t.XYZ()}')
t.XYZ('anotherThing')  # Invoke instance setter

The system is interpreting the getter method as a string rather than a method. I get the following specific results:

(PR) jonathan@jfgdev:/PR$ ./testProperty.py
Type of t.XYZ is <class 'str'>
Traceback (most recent call last):
  File "/mnt/ProgrammingRenaissance/./testProperty.py", line 17, in <module>
    print(f'Invoking getter {t.XYZ()}')
TypeError: 'str' object is not callable

Can anyone see what I am doing wrong? I got the problem on both Python 3.10.6 and Python 3.10.10. If you comment out the invocation of the getter, the same problem shows up when invoking the setter. If I turn the methods into old-fashioned getters and setters, they work so the problem seems to be associated with properties only.

Jonathan
  • 2,635
  • 3
  • 30
  • 49
  • 3
    The way a getter works is that you specifically don't have to call it like a function; so instead of doing `t.XYZ()` you can just refer to `t.XYZ`. That's the whole point of making it a getter and setter. You're treating it like it's just a normal instance method, though. – Random Davis Mar 24 '23 at 15:51
  • There is no getter. The decorator gets rid of it – Mad Physicist Mar 24 '23 at 15:51
  • The decorator rebinds the name `XYZ` to refer to an instance of `property`; it no longer refers to the function now accessible only via `XYZ.fget`. – chepner Mar 24 '23 at 16:14
  • `property` is a class that implements the [descriptor protocol](https://docs.python.org/3/howto/descriptor.html), and `XYZ` is a *class* attribute whose value is an instance of `property`, so `t.XYZ` evaluates to `anyThing.XYZ.fget(t)`, and `t.XYZ = 3` evaluates to `anyThing.XYZ.fset(t, 3)` – chepner Mar 24 '23 at 16:22

0 Answers0