Sam Dillard
Sam Dillard

Reputation: 690

Difference between setters, getters and __set__,__get__

Code:

class Pizza:
  def __init__(self, toppings):
    self.toppings = toppings
    self._pineapple_allowed = False

  @property
  def pineapple_allowed(self):
    return self._pineapple_allowed

  @pineapple_allowed.setter
  def pineapple_allowed(self, value):
    if value:
      password = input("Enter the password: ")
      if password == "Sw0rdf1sh!":
        self._pineapple_allowed = value
      else:
        raise ValueError("Alert! Intruder!")

I'm confused how the @<func>.setter decorator differs from just overwriting the __set__ function in the object. Same with @<func>.getter and __get__.

For that matter, I can't think of a use case for @property over just setting variables in the class.

Am I thinking about this all wrong?

Upvotes: 1

Views: 945

Answers (2)

user2357112
user2357112

Reputation: 281624

I'm confused how the @<func>.setter decorator differs from just overwriting the __set__ function in the object. Same with @<func>.getter and __get__.

You can't overwrite the __set__ method on the property object directly, and even if you could, it wouldn't do anything, because Python goes directly to the property object's class to find __set__ when performing attribute assignment. This goes for most double-double-underscore methods when Python is looking for them as the implementation of language features.

Using .setter instead records the function in an instance attribute of the property object, which __set__ will delegate to to perform the setting.

Upvotes: 1

brc
brc

Reputation: 269

With '@property' descriptor you control a single class attribute, in your case cls.pineapple_allowed, while __get__, __set__ and __delete__ are magic methods of descriptor protocol itself. If you overwrite any of the above method in any class, access/assignment/deletion of ANY class attribute will go thru corresponding magic method.

Upvotes: 1

Related Questions