转自:https://blog.csdn.net/weixin_42681866/article/details/83376484

前文

Python内置有三大装饰器:@staticmethod(静态方法)、@classmethod(类方法)、@property(描述符),其中静态方法就是定义在类里的函数,并没有非要定义的必要;类方法则是在调用类属性、传递类对象时使用;而@property则是一个非常好用的语法糖。@property最大的好处就是在类中把一个方法变成属性调用,起到既能检查属性,还能用属性的方式来访问该属性的作用。

@property应用

让我们先看下@property的应用,其功能1是可定义只读属性,也就是真正意义上的私有属性(属性前双下划线的私有属性也是可以访问的,具体参照这篇文章:私有属性真的是私有的吗?)实例需求是定义类Person,具有年龄和姓名,要求年龄必须等于18,则代码如下:

class Person(object):
def __init__(self, name, age=18):
self.name = name
self.__age = 18 @property
def age(self):
return self.__age xm = Person('xiaoming') # 定义一个人名小明
print(xm.age) # 结果为18
xm.age = -4 # 报错无法给年龄赋值
print(xm.age)

结果如下:

18
Traceback (most recent call last):
xm.age = 18
AttributeError: can't set attribute

在python中定义只读属性非@property莫属,如果细心留意大部分源码,都跑不了@property的身影。而定义只读属性也很简单:以需要定义的属性为方法名(上例age属性定义为方法),其上装饰内置装饰器@property就ok了。

@property真正强大的是可以限制属性的定义。往往我们定义类,希望其中的属性必须符合实际,但因为在__ init __里定义的属性可以随意的修改,导致很难实现。如我想实现Person类,规定每个人(即创建的实例)的年龄必须大于18岁,正常实现的话,则必须将属性age设为只读属性,然后通过方法来赋值,代码如下:

class Person(object):
def __init__(self, name, age):
self.name = name
self.__age = 18 @property
def age(self):
return self.__age def set_age(self, age): # 定义函数来给self.__age赋值
if age < 18:
print('年龄必须大于18岁')
return
self.__age = age
return self.__age xm = Person('xiaoming', 20)
print(xm.age)
print('----------')
xm.set_age(10)
print(xm.age)
print('----------')
xm.set_age(20)
print(xm.age)

为了便于区分结果,增加了分隔符,结果如下:

18
----------
年龄必须大于18岁
18
----------
20

可以看到,通过方法的确能限制输入,但是不是每个人都记得方法名,有什么简化的方法呢?@property就能很轻松办到,修改代码如下:

class Person(object):
def __init__(self, name, age):
self.name = name
self.__age = 18 @property
def age(self):
return self.__age @age.setter
def age(self, age):
if age < 18:
print('年龄必须大于18岁')
return
self.__age = age
return self.__age xm = Person('xiaoming', 20)
print(xm.age)
print('----------')
xm.age = 10
print(xm.age)
print('----------')
xm.age = 20
print(xm.age)

结果和上图一致。两段代码变化的内容:将set_age修改为age,并且在上方加入装饰器@age.setter。这就是@property定义可访问属性的语法,即仍旧以属性名为方法名,并在方法名上增加@属性.setter就行了

@property实现原理

在开头说过,@property是个描述符(decorator),实际上他本身是类,不信的话,可以将上述代码修改如下:

class Person(object):
def __init__(self, name, age):
self.name = name
self.__age = 18 def get_age(self): # 恢复用方法名来获取以及定义
return self.__age def set_age(self, age):
if age < 18:
print('年龄必须大于18岁')
return
self.__age = age
return self.__age age = property(get_age, set_age) # 增加property类

上述代码的运行结果和前面一致,将@property装饰的属性方法再次修改回定义方法名,然后再类的最下方,定义:属性=property(get,set,del),这个格式是固定的,通过源码可以知道原因,property部分源码如下:

class property(object):
def __init__(self, fget=None, fset=None, fdel=None, doc=None):
"""
Property attribute. fget
function to be used for getting an attribute value
fset
function to be used for setting an attribute value
fdel
function to be used for del'ing an attribute
class C(object):
@property
def x(self):
"I am the 'x' property."
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
"""
pass
def __set__(self, *args, **kwargs): # real signature unknown
"""
Set an attribute of instance to value.
"""
pass
def __get__(self, *args, **kwargs): # real signature unknown
"""
Return an attribute of instance, which is of type owner.
"""
pass
def __delete__(self, *args, **kwargs): # real signature unknown
"""
Delete an attribute of instance.
"""
pass

为了不让篇幅过长,同时影响到阅读效果,这边截取了部分,可以看到代码注释里写了官方的@property用法,同时如果是用类来实现的话,必须得按__ init __ 的参数里顺序fget/fset/fdel依次填入get、set、del方法,因为都是默认参数,所以都可以省略不写。

介绍下python的描述符,定义:如果一个类里定义了__ set __ 、__ get __ 、__ delete __三个方法之一,同时给另一个类的属性赋值为实例,那么该类可以称之为描述符。因为描述符的使用目前就python,所以了解下就行了。

总结

关于@property的介绍到此为止,@property装饰器就是一个语法糖(语法糖指那些没有给计算机语言添加新功能,而只是对人类来说更“甜蜜”的语法。 语法糖往往给程序员提供了更实用的编码方式,有益于更好的编码风格,更易读。)。

Python之@property详解及底层实现介绍的更多相关文章

  1. (转)python中@property详解

    转:https://www.cnblogs.com/zhangfengxian/p/10199935.html

  2. (转)python collections模块详解

    python collections模块详解 原文:http://www.cnblogs.com/dahu-daqing/p/7040490.html 1.模块简介 collections包含了一些特 ...

  3. python协程详解,gevent asyncio

    python协程详解,gevent asyncio 新建模板小书匠 #协程的概念 #模块操作协程 # gevent 扩展模块 # asyncio 内置模块 # 基础的语法 1.生成器实现切换 [1] ...

  4. Python基础知识详解 从入门到精通(七)类与对象

    本篇主要是介绍python,内容可先看目录其他基础知识详解,欢迎查看本人的其他文章Python基础知识详解 从入门到精通(一)介绍Python基础知识详解 从入门到精通(二)基础Python基础知识详 ...

  5. Block详解二(底层分析)

    Block专辑: Block讲解一 MRC-block与ARC-block Block详解一(底层分析) 今天讲述Block的最后一篇,后两篇仅仅是加深1,2篇的理解,废话少说,开始讲解! __blo ...

  6. python之struct详解

    python之struct详解 2018-05-23 18:20:29 醉小义 阅读数 20115更多 分类专栏: python   版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议 ...

  7. Python 字符串方法详解

    Python 字符串方法详解 本文最初发表于赖勇浩(恋花蝶)的博客(http://blog.csdn.net/lanphaday),如蒙转载,敬请保留全文完整,切勿去除本声明和作者信息.        ...

  8. python time模块详解

    python time模块详解 转自:http://blog.csdn.net/kiki113/article/details/4033017 python 的内嵌time模板翻译及说明  一.简介 ...

  9. Python中dict详解

    from:http://www.cnblogs.com/yangyongzhi/archive/2012/09/17/2688326.html Python中dict详解 python3.0以上,pr ...

随机推荐

  1. 关于vue-cli的安装

    (一):*安装 vue-cli 参考: https://cn.vuejs.org/v2/guide/installation.html https://github.com/vuejs/vue-cli ...

  2. File Upload(文件上传)

    一句话木马 <?php @eval($_POST['key']); ?> /*eval(phpcode) eval() 函数把字符串按照 PHP 代码来计算. 该字符串必须是合法的 PHP ...

  3. CodeForces - 706B Interesting drink(二分查找)

    Interesting drink Problem Vasiliy likes to rest after a hard work, so you may often meet him in some ...

  4. ❤️【Android精进之路-01】定计划,重行动来学Android吧❤️

    您好,我是码农飞哥,感谢您阅读本文,欢迎一键三连哦. Android精进之路第一篇,确定安卓学习计划. 干货满满,建议收藏,需要用到时常看看.小伙伴们如有问题及需要,欢迎踊跃留言哦~ ~ ~. 前言 ...

  5. 使用metaweblog API实现通用博客发布 之 API测试

    使用metaweblog API实现通用博客发布 之 API测试 使用博客比较少,一则是文笔有限,怕写出的东西狗屁不通,有碍观瞻, 二则是懒,很讨厌要登录到网站上写东西,也没有那么多时间(借口).个人 ...

  6. 【PHP数据结构】其它排序:简单选择、桶排序

    这是我们算法正式文章系列的最后一篇文章了,关于排序的知识我们学习了很多,包括常见的冒泡和快排,也学习过了不太常见的简单插入和希尔排序.既然今天这是最后一篇文章,也是排序相关的最后一篇,那我们就来轻松一 ...

  7. python刷题第二周

    1: 第3章-5 字符转换 (15 分) 本题要求提取一个字符串中的所有数字字符('0'--'9'),将其转换为一个整数输出. 输入格式: 输入在一行中给出一个不超过80个字符且以回车结束的字符串. ...

  8. P4428-[BJOI2018]二进制【树状数组,set】

    正题 题目链接:https://www.luogu.com.cn/problem/P4428 题目大意 长度为\(n\)的\(0/1\)串要求支持 修改一个位置 求区间\([l,r]\)有多少个子区间 ...

  9. 生动直观的Gif图告诉你如何安装Python安装第3方库,在线安装离线安装全都搞定

    前言 学Python的小伙伴都知道,Python学习过程中需要装不少的第3方的库,今天就和大家一起分享下第3方库的安装方法 在线安装(推荐安装式式) 点开Pycharm--file--Project- ...

  10. Dubbo与Zookeeper简单理解

    理论 在<分布式系统原理与范型>一书中有如下定义:"分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统 "; 分布式系统是由一组通过网络进行通信. ...