Get into the habit of writing together! This is the 9th day of my participation in the "Nuggets Daily New Plan · April Update Challenge", click to view the event details .
The concept of Python dynamic attributes may be asked in interviews, and it is also very practical in projects, but it will not be mentioned in general programming tutorials, so you can learn it.
Let's start with a simple example. Create a Student class, and I want to get some information about each student, including name, grades, etc., through an instance. The grade won't be available until the exam is over, so it won't be assigned a value when instantiated.
class Student:
def __init__(self, name):
self.name = name
self.score = None
mike = Student('mike')
复制代码
After the exam, prepare to rate Mike:
mike.score = 999
复制代码
Here, the teacher accidentally typed an extra 9. Generally speaking, the score is 100 points. 999 is an illegal data and should not be successfully assigned. When there are more students, teachers will make more mistakes in scoring, so we must find a way to modify the program to limit the value of score to 0-100 points.
limit value
We define a method, if the input is not an integer of 0-100, let the program report an error, the data is legal, and we modify the score attribute successfully.
def set_score(self, new_score):
if not isinstance(new_score, int):
raise ValueError('score must be int')
if 0 <= new_score <= 100:
self.score = new_score
return self.score
else:
raise ValueError('score invalid')
复制代码
In this way, we use self.score to get it every time we need to get the score, and call the function to modify it when we modify the score:
mike.set_score(999)
复制代码
An error will be reported after the call, because 999 is illegal data. Note that at this time I can still use self.score to set, and no error is reported:
self.score = 999
复制代码
This obviously doesn't work. So we need to provide a mechanism to turn score into a private property that cannot be accessed from the outside. Unfortunately, python's private properties are pseudo-private. Usually we call attributes _
starting with a private attribute, but this is just a protocol and regulation. If you see attributes starting with an underscore, don't access them. You can access it if you insist, but python will not ban it.
Use @property instead.
Although the above method implements the function, it changes the way the attribute is used. It is usually used like this:
# 获取属性
a = mike.score
# 设置属性
mike.score = 99
@property
def score(self):
return self._score
@score.setter
def score(self, new_score):
if not isinstance(new_score, int):
raise ValueError('score must be int')
if 0 <= new_score <= 100:
self._score = new_score
return self._score
else:
raise ValueError('score invalid')
复制代码
Benefits of Dynamic Properties
- The calling method is unified. The way self.score = 99 , not the way the function call.
_score
We will not use it directly. You can use it, but not recommended.- If we have a property that can only be read, just comment out the setter part.
Now let's complete the class, adding the birth and age properties:
from datetime import datetime
class Student:
def __init__(self, name, birth=1920):
self.name = name
self._score = None
self.birth = birth
self.age = datetime.now().year - self.birth
mike = Student('mike')
print(mike.birth)
print(mike.age)
复制代码
-
Birth and age can be calculated from one and the other. There is a data redundancy problem.
-
The age property is problematic like this. When mike is initialized, age has already been calculated. If I access the age property next year, it will be a wrong value. This can be verified by setting age to the current number of seconds:
self.age = datetime.now().second mike = Student('mike') time.sleep(5) print(mike.age) print(datetime.now().second) 复制代码
Dynamic display
@property
def age(self):
return datetime.now().year - self.birth
复制代码
Note, don't set @age.setter here, because it changes dynamically, and your modification will cause data inconsistency, it can only be used as a read-only property.
@property role and application scenarios:
- @property optimizes readability of property reading and setting
- Features that need to restrict attributes;
- Read-only property. If the property can only be read and not written, it is very convenient to use.
- This property changes dynamically according to a changing environment.