python面向对象进阶-08类的property特性
什么是property特性
property装饰器用于将被装饰的方法伪装成一个数据属性,在使用时直接使用
语法
class Goods(object):
@property
def size(self):
return 100
g = Goods()
print(g.size)
property属性的两种方式
1. 装饰器 即:在方法上应用装饰器(推荐使用)
2. 类属性 即:在类中定义值为property对象的类属性(Python2历史遗留)
property属性定义和调用的注意点:
- 定义时,在实例方法的基础上添加 @property 装饰器;并且仅有一个self参数
- 调用时,无需括号
property 作为装饰器使用案例
class A:
def __init__(self,name,key):
self.__name = name
self.__key = key
@property
def key(self):
return self.__key
@key.setter
def key(self,new_key):
if new_key <= 100:
self.__key = new_key
else:
print("key 必须小于等于100")
@key.deleter
def key(self):
print("不允许删除该属性")
del self.__key
# @property
# def name(self):
# return self.__name
#
# @name.setter
# def name(self,new_name):
# self.__name = new_name
a = A("jack",123)
# print(a.name)
# # print(a.get_key())
print(a.key)
a.key = 321
print(a.key)
del a.key
print(a.key)
a.name = "xx"
print(a.name)
property在不同类中的应用
在类的实例方法上应用 @property 装饰器
Python中的类有经典类和新式类,新式类的属性比经典类的属性丰富。( 如果类继object,那么该类是新式类 )
经典类,具有一种 @property 装饰器:
经典类中的属性只有一种访问方式,其对应被 @property 修饰的方法
上代码~
# ############### 定义 ###############
class Goods:
@property
def price(self):
return "laowang"
# ############### 调用 ###############
obj = Goods()
result = obj.price # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
print(result)
新式类,具有三种 @property 装饰器:
新式类中的属性有三种访问方式,并分别对应了三个被 @property、@方法名.setter、@方法名.deleter 修饰的方法
再上代码~~~
#coding=utf-8
# ############### 定义 ###############
class Goods:
"""python3中默认继承object类
以python2、3执行此程序的结果不同,因为只有在python3中才有@xxx.setter @xxx.deleter
"""
@property
def price(self):
print('@property')
@price.setter
def price(self, value):
print('@price.setter')
@price.deleter
def price(self):
print('@price.deleter')
# ############### 调用 ###############
obj = Goods()
obj.price # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
@property
obj.price = 123 # 自动执行 @price.setter 修饰的 price 方法,并将 123 赋值给方法的参数
@price.setter
del obj.price # 自动执行 @price.deleter 修饰的 price 方法
@price.deleter
property作为类属性使用案例
创建值为property对象的类属性
注意:当使用类属性的方式创建property属性时,经典类和新式类无区别
代码走你
class Foo:
def get_bar(self):
return 'laowang'
BAR = property(get_bar)
obj = Foo()
reuslt = obj.BAR # 自动调用get_bar方法,并获取方法的返回值
print(reuslt)
property方法中有个四个参数
第一个参数是方法名,调用 对象.属性 时自动触发执行方法
第二个参数是方法名,调用 对象.属性 = XXX 时自动触发执行方法
第三个参数是方法名,调用 del 对象.属性 时自动触发执行方法
第四个参数是字符串,调用 对象.属性.doc ,此参数是该属性的描述信息
#coding=utf-8
class Foo(object):
def get_bar(self):
print("getter...")
return 'laowang'
def set_bar(self, value):
"""必须两个参数"""
print("setter...")
return 'set value' + value
def del_bar(self):
print("deleter...")
return 'laowang'
BAR = property(get_bar, set_bar, del_bar, "description...")
obj = Foo()
obj.BAR # 自动调用第一个参数中定义的方法:get_bar
obj.BAR = "alex" # 自动调用第二个参数中定义的方法:set_bar方法,并将“alex”当作参数传入
desc = Foo.BAR.__doc__ # 自动获取第四个参数中设置的值:description...
print(desc)
del obj.BAR # 自动调用第三个参数中定义的方法:del_bar方法
由于类属性方式创建property属性具有3种访问方式,我们可以根据它们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除
class Goods(object):
def __init__(self):
# 原价
self.original_price = 100
# 折扣
self.discount = 0.8
def get_price(self):
# 实际价格 = 原价 * 折扣
new_price = self.original_price * self.discount
return new_price
def set_price(self, value):
self.original_price = value
def del_price(self):
del self.original_price
PRICE = property(get_price, set_price, del_price, '价格属性描述...')
obj = Goods()
obj.PRICE # 获取商品价格
obj.PRICE = 200 # 修改商品原价
print(obj.PRICE)
del obj.PRICE # 删除商品原价
综上所述:
定义property属性共有两种方式,分别是【装饰器】和【类属性】,而【装饰器】方式针对经典类和新式类又有所不同。
通过使用property属性,能够简化调用者在获取数据的流程
property+类的封装
例子:
class People:
def __init__(self, name):
self.__name = name
@property # 查看obj.name
def name(self):
return '<名字是:%s>' % self.__name
peo1 = People('nick')
print(peo1.name)
try:
peo1.name = 'LangYiGang'
except Exception as e:
print(e)
列子2
class A:
def __init__(self,key):
self.__key = key
@property
def key(self):
return self.__key
@key.deleter
def key(self):
del self.__key
a = A("123")
# print(a.key)
# print(a.__dict__)
print(a._A__key)
a.__name = 1
print(a.__dict__)
使用property来升级代码的应用:
原代码 (私有属性添加getter和setter方法)
class Money(object):
def __init__(self):
self.__money = 0
def getMoney(self):
return self.__money
def setMoney(self, value):
if isinstance(value, int):
self.__money = value
else:
print("error:不是整型数字")
升级后代码 (使用property升级getter和setter方法)
class Money(object):
def __init__(self):
self.__money = 0
def getMoney(self):
return self.__money
def setMoney(self, value):
if isinstance(value, int):
self.__money = value
else:
print("error:不是整型数字")
# 定义一个属性,当对这个money设置值时调用setMoney,当获取值时调用getMoney
money = property(getMoney, setMoney)
a = Money()
a.money = 100 # 调用setMoney方法
print(a.money) # 调用getMoney方法
升级代码2 (使用property取代getter和setter方法)
重新实现一个属性的设置和读取方法,可做边界判定
class Money(object):
def __init__(self):
self.__money = 0
# 使用装饰器对money进行装饰,那么会自动添加一个叫money的属性,当调用获取money的值时,调用装饰的方法
@property
def money(self):
return self.__money
# 使用装饰器对money进行装饰,当对money设置值时,调用装饰的方法
@money.setter
def money(self, value):
if isinstance(value, int):
self.__money = value
else:
print("error:不是整型数字")
a = Money()
a.money = 100
print(a.money)
通过property来实现计算属性
class Square:
def __init__(self,width):
self.width = width
# self.area = self.width * self.width
@property
def area(self):
return self.width * self.width
s = Square(10)
print(s.area)
s.width = 20
print(s.area)
s.width = 2
print(s.area)