Use of @property in Python

Keywords: Python

When binding attributes, if we assign attributes directly to objects, such as:

p = Person()
p.name= 'Mary'

Let's start with a detailed example (note that double underscored name and age are defined as private variables):

class Person(object):
def __init__(self, name, age):
self.__name = name
self.__age = age

def get_age_fun(self):
return self.__age

def set_age_fun(self, value):
if not isinstance(value, int):
raise ValueError('Age must be a number!')
if value < 0 or value > 100:
raise ValueError('Age must be 0-100')
self.__age = value

def print_info(self):
print('%s: %s' % (self.__name, self.__age))


p = Person('balala',20)
p.__age = 17
print(p.__age) # 17
On the surface of print (p. get_age_fun() 20, the above code "successfully" sets the _age variable 17, but in fact the _age variable and the _age variable inside the class are not a variable!
# The internal _age variable has been automatically changed to _Person_age by the Python interpreter, while the external code adds a _age variable to p. So the call to get_age_fun outputs the initial value

p.set_age_fun(35)
print(p.get_age_fun()) # 35

print(p.print_info()) # balala: 35

Output:

17
20
35
balala: 35

On the surface, the external code "successfully" sets the _age variable 17, but in fact the _age variable and the _age variable inside the class are not a variable!
The internal _age variable has been automatically changed to _Person_age by the Python interpreter, while the external code adds a _age variable to p. So call get_age_fun to output an initial value of 20
set_age_fun changes the value of the age variable through the class interior, so it eventually outputs balala: 35.

Let's make a slight adjustment:

(Note that only one variable name has been changed: the original private property _age single underline is: _age, can also be defined as: age. 
Interpretation: The name of an instance variable starting with an underscore, such as _age, is accessible externally. However, according to the convention, when you see such a variable, it means, "Although it can be accessed, please treat it as a private variable and do not visit it at will." ""
class Person(object):
    def __init__(self, name, age):
        self.__name = name
        self._age = age

    def get_age_fun(self):
         return self._age

    def set_age_fun(self, value):
        if not isinstance(value, int):
            raise ValueError('Age must be a number!')
        if value < 0 or value > 100:
            raise ValueError('Age must be 0-100')
        self._age = value

    def print_info(self):
        print('%s: %s' % (self.__name, self._age))


p = Person('balala',20)
p._age = 17
print(p._age) # 17
print(p.get_age_fun()) # Here is 17 no longer 20,Because this time_age Is a global variable,External directly affects the update values within the class

p.set_age_fun(35)
print(p.get_age_fun()) # 35

print(p.print_info()) # balala: 35

Output:

1 17
2 17
3 35
4 balala: 35

See Private and Global Settings

However, is the above invocation method slightly more complicated than using attributes directly?

Is there a way to access class variables in such a simple way as attributes? Necessary, for class methods
Let's start with a slightly modified example: (Later, we'll use Python's built-in @property decorator to turn a method into a property call.)

Let's get to the point: look at the magic of @property:

 1 class Person(object):
 2     def __init__(self, name, age):
 3         self.__name = name
 4         self.__age = age
 5 
 6     @property
 7     def get_age_fun(self):
 8          return self.__age
 9 
10     @get_age_fun.setter # get_age_fun is the method declared above
11     def set_age_fun(self, value):
12         if not isinstance(value, int):
13             raise ValueError('Age must be a number!')
14         if value < 0 or value > 100:
15             raise ValueError('Age must be 0-100')
16         self.__age = value
17 
18     def print_info(self):
19         print('%s: %s' % (self.__name, self.__age))
20 
21 
22 p = Person('balala',20)
23 p.__age = 17
24 print(p.__age) # 17
25 print(p.get_age_fun) # 20 Be careful not to bring it here.()
26 
27 #p.set_age_fun(35) Note that assignment cannot be invoked in this way
28 p.set_age_fun = 35 #  Here set_age_fun That is, the declared function does not take()
29 print(p.get_age_fun) # 35
30 print(p.print_info()) # balala: 35

Output:

17
20
35
balala: 35

Posted by liamloveslearning on Mon, 06 May 2019 18:55:40 -0700