Python property属性 - 将方法转化为变量的故事(python能做什么)

网友投稿 264 2022-08-26


Python property属性 - 将方法转化为变量的故事(python能做什么)

什么是property属性

一种用起来像是使用的实例属性一样的特殊属性,可以对应于某个方法

# 淡定创建一个胖子老板类In [24]: class FatBoss(): ...: def play(self): ...: print("胖子老板:淡定玩玩斗地主") ...: # 定义property属性 ...: @property ...: def sell(self): ...: print("胖子老板:淡定卖包芙蓉王") ...: # 淡定创建一个实例In [25]: fb = FatBoss() # 淡定调用普通的实例方法In [26]: fb.play() 胖子老板:淡定玩玩斗地主# 淡定调用一下property属性对应的方法,淡定报错。这是为什么?In [27]: fb.sell() 胖子老板:淡定卖包芙蓉王---------------------------------------------------------------------------TypeError Traceback (most recent call last) in ----> 1 fb.sell()TypeError: 'NoneType' object is not callable# 原来property的属性对应的方法,不能写() ,就把它当作 selef.name 来使用,只不过它对应的是一个方法。# 那么就说明property是不能从外部实例传入参数的。In [28]: fb.sell 胖子老板:淡定卖包芙蓉王In [29]: FatBoss.sell Out[29]:

property属性的定义和调用要注意一下几点:

定义时,在实例方法的基础上添加 @property 装饰器;并且仅有一个self参数调用时,无需括号

方法:​​fb.sell()​​property属性:​​fb.sell​​

实例 - 京东商城分页

对于京东商城中显示电脑主机的列表页面,每次请求不可能把数据库中的所有内容都显示到页面上,而是通过分页的功能局部显示,所以在向数据库中请求数据时就要显示的指定获取从第m条到第n条的所有数据 这个分页的功能包括:

根据用户请求的当前页和总数据条数计算出 m 和 n根据m 和 n 去数据库中请求数据

为什么需要m和n的数字,首先需要知道例如mysql的分页查询的sql:​​select * from table_name limit m,n​​

In [34]: class Pager: ...: def __init__(self,current_page): ...: # 用户当前请求的页码 ...: self.current_page = current_page ...: # 每页默认显示10页数据 ...: self.per_items = 10 ...: #定义property属性,进行起始值m的计算 limit m,n ...: @property ...: def calculate_m(self): ...: val = (self.current_page - 1) * self.per_items ...: return val ...: #定义property属性,进行结束值n的计算 limit m,n ...: @property ...: def calculate_n(self): ...: val = self.current_page * self.per_items ...: return val ...: In [35]: In [35]: p = Pager(1) # 传入当前页码就是第一页 In [36]: p.calculate_m Out[36]: 0In [37]: p.calculate_n Out[37]: 10In [38]: In [38]: p = Pager(10) # 传入当前页码就是第10页 In [39]: p.calculate_m Out[39]: 90In [40]: p.calculate_n Out[40]: 100In [41]:

可以从上面的代码中看出,只要加上 ​​@property​​ 作为修饰器,那么就可以将类中的计算方法当作实例变量直接获取。

property属性的有两种方式

装饰器 即:在方法上应用装饰器类属性 即:在类中定义值为property对象的类属性

装饰器方式

在类的实例方法上应用@property装饰器

Python中的类有经典类和新式类,新式类的属性比经典类的属性丰富。( 如果类继object,那么该类是新式类 )

经典类,具有一种@property装饰器

In [41]: class FatBoss: ...: @property ...: def sell(self): ...: return "胖子老板:淡定卖包芙蓉王" In [42]: fb = FatBoss() In [43]: print(fb.sell) 胖子老板:淡定卖包芙蓉王In [44]:

新式类,具有三种@property装饰器

In [45]: class FatBoss: ...: """python3中默认继承object类 ...: 以python2、3执行此程序的结果不同,因为只有在python3中才有@xxx.setter @xxx.deleter ...: """ ...: @property ...: def sell(self): ...: return "胖子老板:淡定卖包芙蓉王" ...: # 定义一个price价格的property属性 ...: @property ...: def price(self): ...: print('@property') ...: # 定义property属性price的setter方法 ...: @price.setter ...: def price(self,value): ...: print('@price.setter') ...: # 定义property属性price的deleter方法 ...: @price.deleter ...: def price(self): ...: print('@price.deleter') ...: In [46]: fb = FatBoss() In [47]: fb.price @propertyIn [48]: fb.price = 17 @price.setterIn [49]: fb.price @propertyIn [50]: print(fb.price) @propertyNone

从上面可以看出,​​fb.price = 17​​​ 则会自动调用 ​​@price.setter​​ 的方法,那么下面来进行详细示例。

property 的 setter 以及 deleter 方法 - 当肥仔白来胖子老板这里买烟,有折扣哦。

有胖子老板的折扣,再也不怕冷了

注意

经典类中的属性只有一种访问方式,其对应被 @property 修饰的方法新式类中的属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法由于新式类中具有三种访问方式,我们可以根据它们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除

In [1]: class FatBoss: ...: def __init__(self): ...: # 一包芙蓉王的原价 ...: self.original_price = 26 ...: # 如果是胖子白来买则会有折扣 ...: self.discount = 0.8 ...: #设置一个property变量 ...: @property ...: def price(self): ...: # 实际价格 = 原价 * 折扣 ...: new_price = self.original_price * self.discount ...: return new_price ...: #设置property的setter方法 ...: @price.setter ...: def price(self,value): ...: self.original_price = value ...: #设置property的delete方法 ...: @price.deleter ...: def price(self): ...: del self.original_price ...: In [2]: fb = FatBoss() In [3]: fb.price Out[3]: 20.8In [4]: fb.price = 17 In [5]: fb.price Out[5]: 13.600000000000001In [6]: del fb.price In [7]: fb.price ---------------------------------------------------------------------------AttributeError Traceback (most recent call last) in ----> 1 fb.price in price(self) 9 def price(self): 10 # 实际价格 = 原价 * 折扣---> 11 new_price = self.original_price * self.discount 12 return new_price 13 #设置property的setter方法AttributeError: 'FatBoss' object has no attribute 'original_price'In [8]:

类属性方式,创建值为property对象的类属性

当使用类属性的方式创建property属性时,经典类和新式类无区别

In [8]: class FatBoss: ...: def sell_ciggite(self): ...: return "芙蓉王" ...: # 定义property ...: SELL = property(sell_ciggite) ...: In [9]: fb = FatBoss() In [10]: print(fb.SELL) # 可以从结果上来看,就是调用了 @property 一样的。 芙蓉王In [11]:

property方法中有个四个参数

第一个参数是方法名,调用 对象.属性 时自动触发执行方法 ===> fb.price第二个参数是方法名,调用 对象.属性 = XXX 时自动触发执行方法 ===> fb.price = 17第三个参数是方法名,调用 del 对象.属性 时自动触发执行方法 ===> del fb.price第四个参数是字符串,调用 对象.属性.doc,此参数是该属性的描述信息

那么这里使用 SELL = property() 的方式,将前面示例中的 setter 以及 deleter 实现

In [17]: class FatBoss: ...: def __init__(self): ...: self.original_price = 26 ...: self.discount = 0.8 ...: def 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 ...: # 定义property属性 ...: Price = property(price,set_price,del_price,"这是price的property描述信息") ...: In [18]: fb = FatBoss() In [19]: fb.Price Out[19]: 20.8In [20]: fb.Price = 17 In [21]: fb.Price Out[21]: 13.600000000000001In [22]: del fb.Price In [23]: fb.Price ---------------------------------------------------------------------------AttributeError Traceback (most recent call last) in ----> 1 fb.Price in price(self) 4 self.discount = 0.8 5 def price(self):----> 6 new_price = self.original_price * self.discount 7 return new_price 8 def set_price(self,value):AttributeError: 'FatBoss' object has no attribute 'original_price'In [24]:

从上面的代码可以看出,使用​​Price = property(price,set_price,del_price,"这是price的property描述信息")​​​ 一行代码,就可以省略 ​​@property @price.setter @price.deleter​​ 三个修饰器的使用了。

综上所述:

定义property属性共有两种方式,分别是【装饰器】和【类属性】,而【装饰器】方式针对经典类和新式类又有所不同。通过使用property属性,能够简化调用者在获取数据的流程

那么说了那么多,有什么应用的例子呢?

不给例子,这就是下场

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方法#100

使用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 = 100print(a.money)


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Python eval 函数 将字符串 转为 有效的表达式(python基础教程)
下一篇:Python 可变参数 *args **kwargs 的再了解(python编程)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~