1

I've recently learned about the @property decorator, but there is (at least) one thing I don't understand about it yet. In this class below, my_name is obviously the property name, but it's not at all clear how the value actually gets assigned. The only assignments are to the underscored _my_name variable, but how does the decorator know that self._my_name corresponds to the my_name property?

class Person:
    def __init__(self, input_name):
        self._my_name = input_name

    @property
    def my_name(self):
        return self._my_name

    @my_name.setter
    def my_name(self, value):
        self._my_name = value
supahcraig
  • 109
  • 6
  • Simply, because that's what you named the property (`def my_name`). What am I missing?? – wim Jan 30 '20 at 06:08
  • What invokes my_name? In the init method it only refers to _my_name (with the underscore). – supahcraig Jan 30 '20 at 15:31
  • 1
    In the init method, nothing invokes `my_name`, you just set a normal attribute. If you wanted, you could use `self.my_name = input_name` in init and this would invoke the property setter (which would then just set the normal attribute the same way). Maybe throw some print statements in there to better understand how/when the setter and getters are invoked. – wim Jan 30 '20 at 16:06

2 Answers2

1

Try looking at it this way, the decorator knows nothing about the internals of the class ex: self._my_name. What it does know, is what function to call when retrieving or setting a value.

p = Person('bob')
name = p.my_name     ## the 'getter' function is called: ultimately p.my_name(self)
p.my_name = 'alice'  ## the 'setter' function is called: ultimately p.my_name(self, 'alice')

There is more stuff going on here, under the hood. Have a look at a similar question: How does the @property decorator work? The top answer does a really good job of explaining what the @property is and does.

Steven Graham
  • 1,220
  • 8
  • 10
  • +1 But maybe it's also worth mentioning: the property could be named differently too (i.e. Python has no hidden sauce which knows that `my_name` property corresponds with `_my_name` attribute). – wim Jan 30 '20 at 16:03
0

A property is a Descriptor. It knows where to get and set _my_name because this is what your getter and setter methods tell it to get and set. Here is a simple example of how a descriptor internally works:

class MyProperty:
    def __init__(self, name):
        # The name of the property we are wrapping
        self.name = name

    def __get__(self, instance, owner):

        # Property was requested from the class, not an instance
        if instance is None:
            return self

        return getattr(instance, self.name)

    def __set__(self, instance, value):

        # Don't overwrite ourself...
        if instance is None:
            return

        setattr(instance, self.name, value)


class Person:
    def __init__(self, input_name):
        self._my_name = input_name

    # Define my_name, that will get/set _my_name
    my_name = MyProperty('_my_name')

jack = Person('Jack')
print(jack.my_name)
jack.my_name = 'Jane'
print(jack.my_name)

The property works a similar way, where it remembers its defined getter, setter and deleter callbacks and call them when the descriptor is retrieved/assigned.

Jordan Brière
  • 1,045
  • 6
  • 8