Use of @ property for Python

  • 2021-11-14 06:28:43
  • OfStack

Catalog 1, several concepts 2, for example
3. Solve the problem
4. Change the way

Usually, when we need to privatize sensitive properties of objects or properties that we don't want to access directly from outside, but sometimes we need to modify these private properties, what should we do?

1. Several concepts

_ a (preceding single underscore), which indicates only conventional private, not true private. __a (double-underlined), which is private and cannot be accessed externally. _a_ (double underscore before and after), which identifies system attributes. (Optional) a_ (post-single underscore), which is an attribute to avoid and preserve keyword conflicts. (Optional)

2. Give an example

Define 1 class:


class Student(object):

    _sex='male'

    __age=0

Execution: (Private properties cannot be accessed externally)


>>> stu = Student()
>>> stu._sex
'male'
>>> stu.__age
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute '__age'
>>>

3. Solve the problem

As we can see from the above class, private properties cannot be accessed in class instances. What should I do? We can define get_age and set_age to implement when we need to query and modify the class's private attribute __age.


class Student(object):

    _sex='male'

    __age=0

    def get_age(self):
        return self.__age

    def set_age(self,age):
        self.__age = age

Execution:


>>> stu = Student()
>>> stu.get_age()   
0
>>> stu.set_age(18) 
>>> stu.get_age()   
18
>>>

4. Change the way

However, the above method is slightly complicated, which is not suitable for classes with more private attributes, so we expect to find a simpler way to solve this problem, such as transforming this private attribute into another attribute. To tell you the good news, Python has already helped us realize it, and this is @ property.


class Student(object):

    _sex='male'

    __age=0

    def get_age(self):
        return self.__age

    def set_age(self,age):
        self.__age = age
    
    @property
    def age(self):
        return self.__age

Execution:


>>> from payhlib import Student
>>> s = Student()
>>> s.age
0
>>> s.set_age(19)
>>> s.age
19
>>

When we converted the __age private attribute to the age attribute above, you may wonder if we can modify it directly since the private attribute is converted to the attribute. The answer is no, because although property converts __age into an attribute, it does not have setter function, so we need to add it.


>>> from payhlib import Student
>>> s = Student()
>>> s.age  
0
>>> s.age=20
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
>>>

Add setter method


class Student(object):

    _sex='male'

    __age=0

    def get_age(self):
        return self.__age

    def set_age(self,age):
        self.__age = age
    
    @property
    def age(self):
        return self.__age
    
    @age.setter
    def age(self,value):
        self.__age=value

Execution:


>>> from payhlib import Student
>>> s = Student()
>>> s.age
0
>>> s.age=20
>>> s.age    
20
>>>

Related articles: