这个章节大部分人都明白@property 的作用。
难道不是把方法转化成属性,可以直接赋值?
那我们说说为什么这么做有什么意义呢?
先用代码一点点引导。
1.避免直接赋值,绕过校验
class Student:
def __init__(self,name,age):
self.name=name
self.age=age
stu=Student("Lady",50)
prtint(stu.age)
stu.age=120
print(stu.age)
打印结果:
50
120
从上边结果看,可以随意读取和修改age并且设置的age还不符合年龄规范。
这显然不行。
首先我们想到的是 用方法加校验 并创建属性,并用方法获取。
class Student:
def __init__(self,name):
self.name=name
def set_age(self,age):
if isinstance(age,int):
if 0<age<120:
self.age=age
else:
print("请输入合法的年龄")
def get_age(self):
return self.age
stu=Student("Lady")
stu.age=120
print(stu.age)
打印结果;
120
上边的代码小伙伴该说了,我不用方法也可以修改值,
stu.age=120
print(stu.age)
并没有报错呀。
为了解释这个原因,我们直接打印这个属性。
print(stu.age)
报错如下:
'Student' object has no attribute 'age'
之所以不会报错 关键点在 stu.age=120 这个步骤是实例化对象。
stu自己给自己添加了一个age 属性,所以不会报错。
这个属性只是属于stu,你换个实例再打印也一定会报错。扯的有点多了,
开始回到正轨。
class Student:
def __init__(self,name):
self.name=name
def set_age(self,age):
if isinstance(age,int):
if 0<age<120:
self.age=age
else:
print("请注意你的年龄范围")
else:
print("请输入合法的年龄")
def get_age(self):
return self.age
stu=Student("Lady")
stu.set_age(1110) #输入不规范的年龄
stu.set_age(10) #设置age,并通过一系列的校验
print(stu.age) # 可以直接调用
print(stu.get_age()) #获取age
打印结果 :
请注意你的年龄范围
10
10
两种方法都可以取到age,
那小伙伴该说 我们就没有必要写get方法了,直接用stu.age调用就行了
(直接用了set 方法的返回值)。
为了防止这种情况发生,规范如下;
set方法里面的返回的属性名前面加上 _,一个小短线。
(实际也不能避免,相对而言安全)
所以写成这样
class Student:
def __init__(self,name):
self.name=name
def set_age(self,age):
if isinstance(age,int):
if 0<age<120:
self._age=age
else:
print("请注意你的年龄范围")
else:
print("请输入合法的年龄")
def get_age(self):
return self._age
stu=Student("Lady")
stu.set_age(1110) #输入不规范的年龄
stu.set_age(10) #设置age,并通过一系列的校验
print(stu.get_age()) #获取age
这样就可以了了 。
2.应用@property 可以把调用的方法像调用属性一样直接用。
Python内置的@property装饰器就是负责把一个方法变成属性调用的:
class Student:
def __init__(self,name):
self.name=name
@property
def age(self):
return self._age
@age.setter
def age(self,age):
if isinstance(age,int):
if 0<age<120:
self._age=age
else:
print("请注意你的年龄范围")
else:
print("请输入合法的年龄")
stu=Student("Lady")
stu.age=10 #设置age,并通过一系列的校验
print(stu.age) #获取age
上边主要以下几点:
1.get 和set 的方法名称都要一样(age)
2.set方法返回的属性要在前面加个"_"
3.@property 是针对get方法
[email protected] 是针对set 方法,是@property本身又创建了另一个装饰器
5.直接可以这样stu.age=10 对象名.方法名进行赋值,
6.只定义getter方法,不定义setter方法是一个只读属性
下边介绍这个特性。
3.只定义getter方法,不定义setter方法就是一个只读属性
class Student:
def __init__(self,name):
self.name=name
@property
def age(self):
return self._age
@age.setter
def age(self,age):
if isinstance(age,int):
if 0<age<120:
self._age=age
else:
print("请注意你的年龄范围")
else:
print("请输入合法的年龄")
@property
def after_3(self):
return self._age+3
stu=Student("Lady")
stu.age=10 #设置age,并通过一系列的校验
print(stu.age) #获取age
stu.after_3=5
打印结果:
AttributeError: can't set attribute
但是我们可以读取 :
print(stu.after_3)
打印结果:
13