一.特性 property
1.什么是 property 特性
property 装饰器可以用于装饰类里面的方法, 让其伪装成一个数据属性, 也就是在调用的时候可以不用加括号
2.定义一个 property 特性
class Person:
def run(self):
print("小王在跑")
@property # 定义property属性
def speak(self):
print("李白在说话")
P1= Person()
P1.run() # 小王在跑
P1.speak # 李白在说话 (调用property属性)
3.为什么要有 property 特性
- 将类的一个函数(方法)定义成 property 特性之后, 不加括号的去使用
[对象].[方法]
的时候, 我们无法察觉自己是执行了一个函数(方法), 这种特性的使用方式遵循了统一访问的原则
4.property 属性的定义和调用的注意点
- 定义时 : 在实例方法的上方添加
@property
装饰器, 并且仅有一个self
参数 - 调用时 : 无需加括号
二.property 属性的使用两种方法
1.第一种 : 使用 property( )
函数 (古老用法, 了解即可)
class Person:
def __init__(self):
self.__name= None
#这是setter方法
def set_name(self,name):
print("设置了名字")
self.__name=name
#这是getter方法
def get_name(self):
print("获取了名字")
return self.__name
# 这是deleter方法
def del_name(self):
print("删除了名字")
del self.__name
name=property(get_name,set_name,del_name) # 这里存放的是"name"的所有操作
P1 = Person()
P1.name = 'Shawn' # 设置了名字 (直接赋值,等同于 P1.set_name('Shawn'))
n = P1.name # 获取了名字 (直接获取数据 ,等同于 P1.get_name())
print(n) # Shawn
del P1.name # 删除了名字 (删除属性)
print(P1.name) # 属性被删除了, 再次查看报错 : "AttributeError" 没有该属性
2.第二种 : 使用 @property
装饰器 (新方法)
- 第二种方法 getter 必须写在 setter 和 deleter 的前面 (说是这么说, 但是实验了一下可以写在后面)
- @property 装饰器必须写在 三者最前面, 并且三者都必须使用被
@property
修饰的同一个函数名, 否则报错
class Person:
def __init__(self):
self.__name= None
@property
def name(self): # 获取
print("设置了名字")
return self.__name
@name.setter
def name(self,name): # 设置
print("设置名字成功")
self.__name=name
@name.deleter # 删除
def name(self):
print("删除了名字")
del self.__name
@name.getter # 获取
def name(self):
print("查看了名字并+'哈哈'")
return self.__name + "哈哈"
P1 = Person()
P1.name = "shawn" # 设置名字成功
n = P1.name # 查看了名字并+'哈哈'
print(n) # shawn哈哈
由上面的例子实验, 我们可以发现一个问题:
@property
下修饰的功能其实是与@name.getter
的功能重复的, 于是我们可以省略@name.getter
不用写, 其实就是@property
替代了@name.getter
3.注意点
- 经典类中的属性只有一种访问方式,其对应被
@property
修饰的方法 - 新式类中的属性有三种访问方式,并分别对应了三个被
@property
、@方法名.setter
、@方法名.deleter
修饰的方法 (获取、修改、删除)
4.总结
- 定义property属性共有两种方式,分别是装饰器和类属性,而装饰器方式针对经典类和新式类又有所不同。
- 通过使用property属性,能够简化调用者在获取数据的流程, 就是重新实现一个属性的设置和读取方法
三.property 特性的应用
1.property 与类的封装组合使用
其实上面的示例就是"property"特性与类的封装的组合使用
2.练习 : 计算圆的周长与面积
import math
class Circle:
def __init__(self,radius):
self.__radius = radius
@property
def area(self):
return f"面积{math.pi * self.__radius ** 2}"
@property
def perimeter(self):
return f"周长{2 * math.pi * self.__radius}"
C1 = Circle(10)
print(C1.area) # 面积:314.1592653589793
print(C1.perimeter) # 周长:62.83185307179586
3.练习 : 计算BMI指数 (体质指数)
- 利用身高与体重的比例来衡量一个人是否过瘦或过肥
- 公式 : BMI = 体重(kg) / (身高(m) ** 2)
- 范围 : (过轻:低于18.5), (正常:18.5-23.9), (过重:24-27), (肥胖:28-32), (非常肥胖, 高于32)
class Person:
def __init__(self,weight,hight):
self.__weight = weight
self.__hight = hight
@property
def BMI(self):
return f"BMI值 : {self.__weight / (self.__hight ** 2)}"
P1 = Person(56,1.73)
print(P1.BMI) # BMI值 : 18.710949246550168