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