python的动态性_python中@property「建议收藏」

Python (58) 2023-09-18 16:12

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说python的动态性_python中@property「建议收藏」,希望能够帮助你!!!。

在讲这个property动态属性之前,先来看一下我们司空见惯的一行代码:

if __name__ == '__main__':
 pass

有时候你可能觉得把代码写在main语句里面太麻烦了,直接运行也是可以的,的确如此,但是这个main方法真的有用,因为它可以选择性执行代码。下面举个例子,在A.py文件中写入这行代码,然后在B.py中引用这行代码,你直接运行B.py文件这段代码就会被执行。这也仅仅是一行代码,如果几千几万行代码呢?我们需要的那段代码还没运行,程序可能就已经卡死了。

print("my info in {}".format(__file__))

但是如果你将这段代码放在main语句里面,你会发现此时运行B.py文件这段代码就不再执行了,因此推荐使用这种。继续我们property动态属性的介绍。

先看一段代码:

from datetime import date,datetime
class User(object):
 def __init__(self, name, birthday, sex):
 self.name = name
 self.birthday = birthday
 self.sex = sex
 self._age = 0 
# 此处的单下划线并不是私有属性,只是给人一种特殊的感觉,只有__双下化线Python才是私有变量
 # def get_age(self):
 # # print(self.birthday.year)
 # return datetime.now().year-self.birthday.year
 @property
 def age(self):
 return datetime.now().year - self.birthday.year
 @age.setter
 def age(self, value):
 self._age = value
# print("my info in {}".format(__file__))
if __name__ == '__main__':
 user = User("envy", date(year=2008, month=8, day=8), "男")
 # print(user.get_age())
 print(user.age)
 user._age = 20
 print(user._age)

一般存入数据库的是年龄,但是我们又不能直接传入年龄,因为时间在改变,年龄也会变,以后更新会很难。我们可以新建一个方法,处理一下年龄不就可以么?。但是我们在设计数据库的时候是有一个age字段的,因此考虑不通过调用user.get_age()这种方式,最好是user.age方式呢?可以的,此时property动态属性就派上用场了,简单一点就是property可以将函数调用变为属性调用,而且在内部可以增加自己的逻辑,不过这个property只是一种getter方法,那么有没有setter方法呢?可以,因为你已经get到了age的值,当然就可以对其进行操作了。

不知道这样介绍是不是很好理解,我觉得还是有必要再详细一点,再来看一个例子,这个例子非常常见:获取学生的成绩。成绩都只有在考试之后才有的,因此你实例化一个学生的时候,一般就是姓名,学号,以及科目,为了简化此处只假设学生初始化只有姓名这一个属性,后续也只增加成绩这个属性,多的没有必要。

class Student:
 def __init__(self, name):
 self.name = name
 self._score = None # 此处写self.score = None 也可以
test= Student('test')

考试只后,test这位同学的成绩出来了98分,不过老师不小心多打了一个8,变成988分。这个可以理解毕竟学生太多,老师打分出现纰漏的情况可能会出现,所以我们想限制分数值必须在 0-100 分之间(百分制)。

test.score = 988

最简单的方式就是定义一个可以检查分数的函数:

 def set_score(self, new_score):
 if not isinstance(new_score, int):
 raise ValueError("对不起,分数必须是整数")
 if 0 <= new_score <=100:
 self._score = new_score
 else:
 raise ValueError("对不起,分数必须在0-100之间")

然后直接调用这个方法进行分数赋值,这的确可以检查赋值的分数是否满足要求,但是我们依然可以使用self._score=98进行赋值。尽管Python中提供了私有属性,但这其实是伪私有(_ 开头),只是一种协议和规定,不推荐去访问以下划线开头的属性,但这并不表示不能访问。那么这样,使用prperty动态属性就能解决这个问题,因为它将函数调用转为属性调用。

property动态属性只是类似于getter方法,可以使用方法名.setter达到setter的目的

class Student:
 def __init__(self, name):
 self.name = name
 self._score = None
 @property
 def score(self):
 return self._score
 @score.setter
 def score(self, new_score):
 if not isinstance(new_score, int):
 raise ValueError("对不起,分数必须是整数")
 if 0 <= new_score <= 100:
 self._score = new_score
 return self._score
 else:
 raise ValueError("对不起,分数必须在0-100之间")
if __name__ == '__main__':
 test = Student("test")
 test.score = 98

当然其实这里你还是可以使用self._score=98进行赋值,不过大家都不会这么干,因为这里已经有self.score=98了,谁还会在前面多加一横呢?

总结一下:

@property 优化了属性读取和设置的可读性,一般用于需要限制属性的特征的场合;它是只读属性。如果属性只读,不可以写,此时用它是最合适不过了,并且记住这个属性会根据环境而动态改变。(property一般都有返回值,正如Java中的getter和setter方法一样,前者有返回值,后者没有)

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

发表回复