Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >python学习笔记6.3-类的属性函数(@property)

python学习笔记6.3-类的属性函数(@property)

作者头像
锦小年
发布于 2018-01-02 06:23:48
发布于 2018-01-02 06:23:48
81700
代码可运行
举报
文章被收录于专栏:锦小年的博客锦小年的博客
运行总次数:0
代码可运行

属性函数(@property) 在对象中两个很重要的元素就是属性和方法,在调用的时候两者是有区别的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class People:
    def __init__(self,first_name,last_name):
        self.first_name = first_name
        self.last_name  = last_name

    def get_first_name(self):
        return self.first_name

a = People('lala','ouyang')
print(a.get_first_name())
print(a.first_name)

从例子中我们可以发现,一样的结果,但是调用的过程不一样(虽然其实也就是多一个括号而已),那么有没有一种办法,使得我们调用属性的时候就会自动调用相应的方法,也就是增加一些额外的处理过程(例如类型检查或者验证)。这时候属性函数(@property)就能给我们提供很好的解决方案。 首先是最简单的例子,自动调用get,set,del函数对属性的处理。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class People:
    def __init__(self,name):
        self.name = name
    #getter function
    @property #属性函数
    def name(self):
        return self._name

    #setter function
    @name.setter
    def name(self,name):
        self._name = name

    #deleter function
    @name.deleter
    def name(self):
        raise AttributeError('Can not delete the name')

a = People('leida')
print(a.name) #calling the getter function automatic when we get the attribute
a.name = 'libai'  #Calling the setter function automatic when we set the attribute
print(a.name)
del a.name  #Calling the deleter function automatic when we delete the attribute

leida
Traceback (most recent call last):
libai
  File "D:/home/WX/test_clsaa.py", line 65, in <module>
    del a.name  #Calling the deleter function automatic when we delete the attribute
  File "D:/home/WX/test_clsaa.py", line 59, in name
    raise AttributeError('Can not delete the name')
AttributeError: Can not delete the name

正如例子中这样。要定义对属性的访问,一种最简单的方法就是将其定义为property。比如说,增加对属性的类型检查:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class People:
    def __init__(self,name):
        self.name = name
    #getter function
    @property #属性函数
    def name(self):
        return self._name

    #setter function
    @name.setter
    def name(self,name):
        if not isinstance(name,str):
            raise TypeError('name must is string type')
        self._name = name

    #deleter function
    @name.deleter
    def name(self):
        raise AttributeError('Can not delete the name')

a = People(12) #calling the setter function automatic when create the instance

Traceback (most recent call last):
  File "D:/home/WX/test_clsaa.py", line 63, in <module>
    a = People(12) #calling the setter function automatic when create the instance
  File "D:/home/WX/test_clsaa.py", line 45, in __init__
    self.name = name
  File "D:/home/WX/test_clsaa.py", line 55, in name
    raise TypeError('name must is string type')
TypeError: name must is string type

当我们实现一个property时,底层数据仍然需要保存在某个地方,因而在get和set的方法中,可以看到直接对_name操作的,这就是数据实际保存的地方。但是,也发现在init()方法中任然是对self.name操作的。但是实际情况是我初始化的时候程序仍旧是对self._name操作的。(这点我也还不理解,应该不是这样的啊.但是必须这么写,不然会报错)。 对于已经存在的get,set,del方法,同样也可以定义为property:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class People:
    def __init__(self,name):
        self.name = name
    def get_name(self):
        print('calling the get function')
        return self._name
    def set_name(self,name):
        print('calling the set function')
        self._name = name
    def del_name(self):
        del self._name
    name = property(get_name,set_name,del_name)

a = People('libai') #calling the setter function automatic when create the instance

同时,在set_name 函数中做了打印标记,发现在init()方法中确实调用了set_name()函数。

Property属性实际上就是把一系列的方法绑定到一起。如果检查类的property属性,就会发现property自身所持有的属性fget,fset,fdel所代表的原始方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
print(People.name.fget)
print(People.name.fset)
print(People.name.fdel)

一般来说,我们不会直接去调用fset或者fget,但是当我们调用property属性时会自动触发对这些方法的调用。 上面例子中的两种写法,一般倾向于第二种写法,特别是如果需要对某个普通的属性额外增加处理步骤时,可以在不修改已有代码的情况下将这个属性提升为一个property。 Property也可以用来定义需要计算的属性,这类属性并不会实际被保存起来,而是根据需要完成计算。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import math
class Circle:
    def __init__(self,radius):
        self.radius = radius

    @property
    def area(self):
        return math.pi * self.radius**2
    @property
    def perimeter(self):
        return 2*math.pi*self.radius

c = Circle(5)
print(c.area)      #do not need (): c.area instead of c.area()
print(c.perimeter)

78.53981633974483
31.41592653589793

这样的写法就会使得实例的接口变得统一,本来用方法实现的计算调用的时候用属性就可以,很好的避免了方法、属性傻傻分不清的情况了。 个人建议,不要在代码中不断重复使用@property,这样会使得代码变得臃肿,而且难以阅读,容易出错。同样的任务,利用描述符或者闭包也能够很好的完成(以后会详细解释)。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Python - 面向对象编程 - @property
可以实现在不破坏类封装原则的前提下,让开发者依旧使用 对例对象.属性 的方式操作类中的属性
小菠萝测试笔记
2021/09/08
3390
没看完这11 条,别说你精通 Python 装饰器
对于每一个学习 Python 的同学,想必对 @ 符号一定不陌生了,正如你所知, @ 符号是装饰器的语法糖,@符号后面的函数就是我们本文的主角:装饰器。
小小詹同学
2019/08/16
9980
没看完这11 条,别说你精通 Python 装饰器
python3--面向对象的三大特性:封装,property,classmethod,staticmethod
AttributeError: type object 'A' has no attribute '__N'
py3study
2018/08/02
9970
Python3中的特性-----Property介绍
在python 中 属性 这个 实例方法, 类变量 都是属性. 属性, attribute
我被狗咬了
2019/10/14
8390
Python面向对象之封装(04)
封装是面向对象编程的一大特点,面向对象编程的第一步将属性和方法封装到一个抽象类中,外界使用类创建对象然后让对象调用方法,对象方法的的细节都被封装在类的内部。
PM小王
2019/07/02
5640
神奇的Python property装饰器:1行代码让Python方法秒变属性
这段代码的主要功能就是通过word方法返回一个字符串。而最后一行直接访问了word方法。在Python语言中,任何东西都可视为对象,方法也不例外。所以直接输出了word方法的对象形式。
蒙娜丽宁
2021/04/19
1.2K0
神奇的Python property装饰器:1行代码让Python方法秒变属性
Python入门之面向对象编程(四)Python描述器详解
本文分为如下部分 引言——用@property批量使用的例子来引出描述器的功能 描述器的基本理论及简单实例 描述器的调用机制 描述器的细节 实例方法、静态方法和类方法的描述器原理 property装饰器的原理 描述器的应用 参考资料 引言 前面python面向对象的文章中我们讲到过,我们可以用@property装饰器将方法包装成属性,这样的属性,相比于其他属性有一个优点就是可以在对属性赋值时,进行变量检查,举例代码如下、 class A: def __init__(self, name, sco
Jetpropelledsnake21
2018/05/02
9150
说说Python中的property
最近在项目中,发现项目越来越大之后,之前的编写方式会留下很多坑,因此最近专门研究了一下静态语言中的方法,比如java中的bean这玩意,发现这种方式引入后,可以很有效的解决这类问题。
点点寒彬
2020/03/18
5930
Python描述器
以上代码实现了温度的摄氏温度和华氏温度之间的自动转换。其中Temperature类含有实例变量fahrenheit和类变量celsius,celsius由描述器Celsius进行代理。由这段代码引出的三点疑问:
职场亮哥
2020/10/10
5340
Python - 描述器
我们可以使用 Python 自带的 property 装饰器 来控制属性的访问,下面这个例子通过 property 控制了 Person 的 age 属性的访问和修改
小歪
2019/05/14
9680
Python第九周 学习笔记(1)
描述器 ---- get(self, instance, owner) 访问属性时调用 set(self, instance, value) 当对属性赋值时调用 delete(self, instance) 删除属性时调用 self指代当前实例 instance是owner的实例 owner是属性的所属的类 描述器实现前提是描述器类实例作为类属性 当只实现get时 (非数据描述符),属性查找顺序是本实例优先,get方法次之 当实现get和set时(数据描述符) ,属性查找顺序是get方法优先 本
py3study
2020/01/10
5870
Python 学习入门(36)—— @property属性
@property 可以将python定义的函数“当做”属性访问,从而提供更加友好访问方式,但是有时候setter/getter也是需要的
阳光岛主
2019/02/18
4820
这个 Python 知识点,90% 的人都得挂~
学习 Python 这么久了,说起 Python 的优雅之处,能让我脱口而出的, Descriptor(描述符)特性可以排得上号。
青南
2020/08/27
5410
这个 Python 知识点,90% 的人都得挂~
python学习笔记6.6-类的惰性属性
本文介绍了Python中类的惰性属性,包括定义、访问和计算。惰性属性使用描述符来延迟属性的计算,从而提高程序的性能。同时,介绍了两种实现惰性属性的方法,包括使用装饰器和描述符。
锦小年
2018/01/02
7570
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
8550
Python之面向对象三
Python自动化开发学习7
class A 经典类写法,查找方式深度优先 class A(object) 新式类写法,查找方式广度优先 上面是python2的语法,python3里可能已经没有经典类了。不管有没有,都用形式类来写就对了。 上面都是上节讲的内容,再讲一下构造函数的问题。 Father.__init__(self,name,age) 这个是经典类的构造函数写法,把父类的名字写在前面,但是问题是若干是多继承呢。这一句显然只继承了一个父类。其他父类的属性就没有继承到了。那么就是有几个父类要写几个构造函数了。 super(Son,self).__init__(name,age) # super就一次能把所有父类的属性继承到了 多继承的情况可能用不到,或者也可以用其他方法来替代,比如组合。暂时就掌握这么多了 super(Son, self).__init__(*args, **kwargs) # 这样写,不指定继承哪些参数,而是全部继承过来,推荐。
py3study
2020/01/07
9930
Python类属性装饰器使用技巧
在Python中,装饰器是一个强大而灵活的工具,用于修改函数或方法的行为。对于类属性,Python也提供了装饰器,使得我们可以对类的属性进行控制和管理。类属性装饰器可以用于数据验证、懒加载、计算属性等场景。本文将详细介绍Python类属性装饰器的概念、用法及其实际应用,并通过示例代码帮助全面掌握这一重要工具。
sergiojune
2024/07/12
2910
Python类属性装饰器使用技巧
浅析Python装饰器中的@property
定义了一个 Exam 类,为了避免直接对 _score 属性操作,提供了 get_score 和 set_score 方法,这样起到了封装的作用,把一些不想对外公开的属性隐蔽起来,而只是提供方法给用户操作,在方法里面,可以检查参数的合理性等。
Go进阶者
2021/04/13
6760
浅析Python装饰器中的@property
Python OOP-4
8. 类的成员描述符(属性) 类的成员描述是为了在类中对类的成员属性进行相关操作而创建的一种方式 get:获取属性的操作 set:修改或添加属性操作 delete:删除属性的操作 如果想使用类的额成员描述符,大概有三种方法 使用类实现描述器 使用属性修饰符 使用property函数 property函数很简单 property(fget, fset, fdel, doc) 无论哪种修饰符都是为了对成员属性进行相应的控制 类的方式:适用多个类中的多个属性共用同一个描述符 property:适用当前类中使用,可
ruochen
2021/03/01
4440
Python  OOP-4
@classmethod与@staticmethod以及属性函数@property
@classmethod @propery @staticmethod 装饰器
禹都一只猫olei
2018/12/27
9550
相关推荐
Python - 面向对象编程 - @property
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档