Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Python property属性 - 将方法转化为变量的故事

Python property属性 - 将方法转化为变量的故事

作者头像
Devops海洋的渔夫
发布于 2019-06-02 05:54:13
发布于 2019-06-02 05:54:13
77300
代码可运行
举报
文章被收录于专栏:Devops专栏Devops专栏
运行总次数:0
代码可运行

什么是property属性

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 淡定创建一个胖子老板类
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)
<ipython-input-27-a42050ff6e4f> in <module>
----> 1 fb.sell()

TypeError: 'NoneType' object is not callable

# 原来property的属性对应的方法,不能写() ,就把它当作 selef.name 来使用,只不过它对应的是一个方法。
# 那么就说明property是不能从外部实例传入参数的。
In [28]: fb.sell                                                                     
胖子老板:淡定卖包芙蓉王

In [29]: FatBoss.sell                                                                
Out[29]: <property at 0x7fd84f7d42c8>

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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]: 0

In [37]: p.calculate_n                                                               
Out[37]: 10

In [38]:  

In [38]: p = Pager(10) # 传入当前页码就是第10页                                      

In [39]: p.calculate_m                                                               
Out[39]: 90

In [40]: p.calculate_n                                                               
Out[40]: 100

In [41]:  

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

property属性的有两种方式

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

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
In [41]: class FatBoss: 
    ...:     @property 
    ...:     def sell(self): 
    ...:         return "胖子老板:淡定卖包芙蓉王"                                    

In [42]: fb = FatBoss()                                                              

In [43]: print(fb.sell)                                                              
胖子老板:淡定卖包芙蓉王

In [44]:   

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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                                                                         
@property

In [48]: fb.price = 17                                                                    
@price.setter

In [49]: fb.price                                                                         
@property

In [50]: print(fb.price)                                                                  
@property
None

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

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

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

注意

  • 经典类中的属性只有一种访问方式,其对应被 @property 修饰的方法
  • 新式类中的属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法
  • 由于新式类中具有三种访问方式,我们可以根据它们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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.8

In [4]: fb.price = 17                                                                     

In [5]: fb.price                                                                          
Out[5]: 13.600000000000001

In [6]: del fb.price                                                                      

In [7]: fb.price                                                                          
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-7-8b8b5efb4572> in <module>
----> 1 fb.price

<ipython-input-1-56837ac7ad5b> 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属性时,经典类和新式类无区别

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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.8

In [20]: fb.Price = 17                                                                    

In [21]: fb.Price                                                                         
Out[21]: 13.600000000000001

In [22]: del fb.Price                                                                     

In [23]: fb.Price                                                                         
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-23-f1fcd9b37f75> in <module>
----> 1 fb.Price

<ipython-input-17-dd23c68d302b> 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方法
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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方法
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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方法

重新实现一个属性的设置和读取方法,可做边界判定

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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)
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.12.30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【从零学习python 】61.Python中的property属性详解和应用示例
对于京东商城中显示电脑主机的列表页面,每次请求不可能把数据库中的所有内容都显示到页面上,而是通过分页的功能局部显示,所以在向数据库中请求数据时就要显示的指定获取从第m条到第n条的所有数据。这个分页的功能包括:
全栈若城
2024/02/29
1950
Python中property的使用技巧
既要保护类的封装特性,又要让开发者可以使用 对象.属性 的方式操作方法,@property 装饰器,可以直接通过方法名来访问方法,不需要在方法名后添加一对 () 小括号。
忆想不到的晖
2021/04/04
1.5K0
Python进阶-面向对象
类的成员 类的成员可以分为三类:字段、方法、属性 一:字段: 普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同 普通字段属于对象 静态字段属于类 字段的定义和使用 class Province: # 静态字段 country = '中国' def __init__(self,name): # 普通字段 self.name = name # 直接访问普通字段 obj = Province('北京') print obj
洗尽了浮华
2018/01/22
7320
Python进阶-面向对象
python中@property和pro
1、基本的@property使用,可以把函数当做属性用 class Person(object): @property def get_name(self): print('我叫xxx') def main(): person = Person() person.get_name if __name__ == '__main__': main() 2、@property的set,deleter,get class Goods(objec
py3study
2020/01/17
5920
【十四】python面向对象之类的字、方法和属性
注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段。而其他的成员,则都是保存在类中,即:无论对象的多少,在内存中只创建一份。
菲宇
2019/06/13
4400
【十四】python面向对象之类的字、方法和属性
Python之面向对象三
面向对象的三大特性: 多态 多态指的是一类事物有多种形态。Python3天生支持多态。 动物有多种形态:人,狗,猪 import abc class Animal(metaclass=abc.ABCMeta): #同一类事物:动物 @abc.abstractmethod def talk(self): pass class People(Animal): #动物的形态之一:人 def talk(self): print('say hello') c
新人小试
2018/04/12
8310
Python之面向对象三
python3--面向对象的三大特性:封装,property,classmethod,staticmethod
AttributeError: type object 'A' has no attribute '__N'
py3study
2018/08/02
9670
深入理解Python面向对象-类成员
Python是一个面向对象的语言,但是因为python语言的特性,我们大多的python程序员只是把它当做一个工具,在我们项目的实际使用中除了使用Django框架以外,其他的都是使用python最基础的方式,完全跟pythonic没有一点关系,当然主要还是因为我们能力太差。面向对象是书写各种框架的基础,python的面向对象不仅拥有通用面向对象的特性,而且还拥有一些极其强大的特性,可以让我们把它的便利性发挥到极致。本篇将详细介绍Python 类的成员、成员修饰符、类的特殊成员。
星星在线
2019/05/28
7390
Python基础(10)——属性
子类没有实现__init__方法时,默认自动调用父类的。 如定义__init__方法时,需自己手动调用父类的 __init__方法
羊羽shine
2019/05/28
3230
Python中三个装饰器函数用法(property、staticmethod、classmethod )
类方法通过@classmethod装饰器实现,类方法和普通方法的区别是, 类方法只能访问类变量,不能访问实例变量
Python学习者
2023/04/12
4180
Python - 面向对象编程 - @property
可以实现在不破坏类封装原则的前提下,让开发者依旧使用 对例对象.属性 的方式操作类中的属性
小菠萝测试笔记
2021/09/08
3080
python粗谈面向对象(二)
super并不是一个函数,是一个类名,形如super(B, self)事实上调用了super类的初始化函数,产生了一个super对象;Python的多继承类是通过mro的方式来保证各个父类的函数被逐一调用,而且保证每个父类函数只调用一次(如果每个类都使用super),并且按照mro序列一次调用。下面是一个小练习:
py3study
2020/01/17
6530
Python 类对象和实例对象访问属性的区别、property属性
下面的一个小demo,定义了一个省份类  Province ,即类对象 Province ,开辟了一块内存空间,空间中存放着 类属性 country 和 __init__()方法 。
用户7886150
2020/12/20
3.9K0
面向对象的三大特性(封装、继承、多态)
继承 什么是继承 继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类 python中类的继承分为:单继承和多继承 class ParentClass1: #定义父类 pass class ParentClass2: #定义父类 pass class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass pass class SubClass2
用户1214487
2018/01/23
4.2K0
面向对象的三大特性(封装、继承、多态)
面向对象封装、继承、多态
身份运算符用于 比较 两个对象的 内存地址 是否一致 —— 是否是对同一个对象的引用
py3study
2020/01/16
6380
面向对象封装、继承、多态
python使用@property @x
@property可以将python定义的函数“当做”属性访问,从而提供更加友好访问方式,但是有时候setter/deleter也是需要的。 1》只有@property表示只读。 2》同时有@property和@x.setter表示可读可写。
py3study
2020/01/09
6120
Python3中的特性-----Property介绍
在python 中 属性 这个 实例方法, 类变量 都是属性. 属性, attribute
我被狗咬了
2019/10/14
7890
神奇的Python property装饰器:1行代码让Python方法秒变属性
这段代码的主要功能就是通过word方法返回一个字符串。而最后一行直接访问了word方法。在Python语言中,任何东西都可视为对象,方法也不例外。所以直接输出了word方法的对象形式。
蒙娜丽宁
2021/04/19
1.2K0
神奇的Python property装饰器:1行代码让Python方法秒变属性
7.0 Python 面向对象编程
python是一种面向对象的编程语言,面向对象编程(Object-Oriented Programming,OOP)是一种编程思想,其核心概念是“对象”。对象是指一个具有特定属性和行为的实体,而面向对象编程就是通过对这些实体进行抽象、分类、封装和继承等操作,来实现程序的结构和逻辑。在python中,我们可以通过定义类、创建实例和调用方法等方式,来实现面向对象编程的思想,从而编写出更加灵活、可扩展、易维护的程序。
王瑞MVP
2023/08/14
2870
python之@property装饰器使用
@property是Python内置的一种装饰器。将类方法转换为类属性,可以用 . 直接获取属性值或者对属性进行赋值。
用户7886150
2021/01/21
6190
相关推荐
【从零学习python 】61.Python中的property属性详解和应用示例
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验