This is the 13th day of my participation in the August More text Challenge. For details, see: August More Text Challenge

In Python, there is an @ Property (descriptor) decorator that decorates methods. Using the @ Property decorator to decorate a class method turns the method into a property call, allowing you to both check the property and access the method as a property.

The use and function of @Property

Modifies methods to make them accessible like properties

In simple terms: the class instance method is called as a property to make encapsulation better, so that developers can use, as simple as calling the property.

Look at the following code:

class Person:
    def __init__(self) :
        self.name = "Zhang"
        self.birthday = 1997

    @property
    def get_age_with_property(self) :
        age = datetime.now().year - self.birthday
        return age

    def get_age_without_property(self) :
        age = datetime.now().year - self.birthday
        return age


per = Person()
print(per.name)
print(per.get_age_without_property())
print(per.get_age_with_property)  Call get_age_with_property without adding ()
Copy the code

Get_age_with_property () can be called using per.get_age_with_property (), just as if it were a property; Get_age_without_property () does not use the @property decorator and cannot be accessed in this way.

Set getter and setter methods for properties

class Person:
    def __init__(self) :
        self.name = "Zhang"
        self.__birthday = 1997

    @property
    def birthday(self) :
        return self.__birthday

    @birthday.setter
    def birthday(self, value) :
        self.__birthday = value


per = Person()
print(per.birthday)
per.birthday = 2222
print(per.birthday)
Copy the code

That’s how we write the @ Property decorator. The @property decorator decorates the get function and the @get function name. The setter decorator decorates the set function, respectively, to set the properties like getter and setter methods.

Set the read-only property to prevent the property from being modified

What if you want to make a class property read-only and unmodifiable? At sign property is the best choice, which creates read-only properties.

class Person:

    def __init__(self) :
        self.name = "Zhang"
        self.__birthday = 1997

    @property
    def birthday(self) :
        return self.__birthday

per = Person()
print(per.birthday)
per.birthday = 2222
print(per.birthday)
Copy the code

The execution result is as follows:“AttributeError: Can’t set attribute” is displayed. As long as we only use@propertyDecorator, not used@birthday.setterDecorator allows the user to only use the property, but not modify it.

@ Property implementation principle

As we said at the beginning,@propertyIs a descriptor, which is actually a class itself. We can tell from the source code

A descriptor is a class that internally defines one or more of the __get__(), __set__(), or __delete_() methods and assigns an instance of another class’s attributes. If we define a class that implements __get__(), __set__(), and __delete_(), then the class is a descriptor and has the same functionality as @Property.

class MyProperty:

    def __init__(self, get=None.set=None) :
        self.__get = get
        self.__set = set

    def __get__(self, instance, type) :
        return self.__get(instance)

    def __set__(self, instance, value) :
        if self.__set is None:
            raise AttributeError("this attribute is read-only")
        return self.__set(instance, value)

    def setter(self, set) :
        self.__set = set
        return self

Copy the code

__get__(self, instance, type);

  • Self: the descriptor object itself
  • Instance: An instance object of the proxied class
  • Type: The class to which the descriptor object is attached, which is actually the class to which instance belongs

Next, we decorate the Person class method with the custom MyProperty descriptor above to do the same thing as @Property:

class Person:

    def __init__(self) :
        self.name = "Zhang"
        self.__birthday = 1997

    @MyProperty
    def birthday(self) :
        return self.__birthday

    @birthday.setter
    def birthday(self, value) :
        self.__birthday = value


per = Person()
print(per.birthday)
per.birthday = 2222
print(per.birthday)
Copy the code

conclusion

So much for @Property. The @ Property decorator is a syntax sugar. Syntax sugar in Python often gives us a more practical way to code, which helps to create a better coding style, making the code more efficient and readable.

Finally, I would like to thank my girlfriend for her tolerance, understanding and support in work and life.