property

property装饰器的应用来自这样一个问题:如果对实例的属性值不加以限制,那么实例的属性值会出现明显不合理的情况,为了解决这个问题也许你会思考在对属性的修改时利用实例方法加以限制,但python中引入了@property 装饰器更方便的解决这个问题。

class Person(object):
def __init__(self, age=1):
self.age = age
p = Person()
p.age = -1 # 这显然是不合理的
class Person(object):
def __init__(self):
self._age = 1 # 私有属性,外部无法直接修改和访问 def age_setter(self, age):
if 0 < age < 120 and isinstance(age, int):
self._age = age
else:
raise ValueError('age must between 0-120 and be integer')
def age_getter(self):
return self._age
# 这时虽然做到了属性值的控制,但是每次设置和获取值的时候要调用不同的方法,不太方便

@property 装饰器兼顾了方便和控制,让实例的使用显得更加优雅,提高了可用性。另外,@property装饰器不设置setter时,就是一个只读属性,相当于对属性起到了保护作用,如下实验

class Person(object):
def __init__(self):
self._height = 1 @property # 这里就是height的getter
def height(self):
return self._height @height.setter
def height(self, height):
if 0 < height < 220 and isinstance(height, int):
self._height = height
else:
raise ValueError('height must between 0-220 and be an integer') @property
def normal_weight(self):
return round(22.86*(self.height/100)**2*2, 2) p = Person()
p.height = 190
print(p.height)
print(p.normal_weight)
------ 结果 ——————
190
165.05

__set__ 和 _get_

理解set和get方法,实际上必须知道描述器是什么,成为一个描述器,一个类必须至少有__get____set____delete__方法被实现。如果一个对象同时定义了 __get__()__set__(),它叫做资料描述器(data descriptor)。仅定义了 __get__() 的描述器叫非资料描述器(non-data descriptor)。

__get__(self, obj, type=None) --> value
定义了当描述器的值被取得的时候的行为。instance是拥有该描述器对象的一个实例。owner是拥有者本身
__set__(self, obj, value) --> None
定义了当描述器的值被改变的时候的行为。instance是拥有该描述器类的一个实例。value是要设置的值。
__delete__(self, instance) --> None
定义了当描述器的值被删除的时候的行为。instance是拥有该描述器对象的一个实例。

几个注意事项:资料描述器的执行顺序优先于实例字典,而实例字典的执行顺序优先于非资料描述器,重写getattribute可能会阻止描述器的使用。关于属性查找优先顺序的问题,后面会写一篇博客描述和实验,这里不重复。

class Descriptor:
def __get__(self, instance, owner):
print('1 get called,', 'instance is', instance, ',owner is', owner)
return instance._a def __set__(self, instance, value):
print('2 set called,', 'instance is', instance, ',value is', value)
instance._a = value * 2 class T:
desc = Descriptor() # 类方法
def __init__(self):
self._a = 123 t = T()
t.desc = 5
print('result:', t.desc)

其实这里的使用已经很像@property了,但@property则更加简单方便。

--------结果------------
2 set called, instance is <__main__.T object at 0x00000182D90DC630> ,value is 5
1 get called, instance is <__main__.T object at 0x00000182D90DC630> ,owner is <class '__main__.T'>
result: 10

描述器协议是一个理解python内部机制的知识点,属性(property), 方法(bound和unbound method), 静态方法和类方法都是基于描述器协议的。

参考:

https://pyzh.readthedocs.io/en/latest/Descriptor-HOW-TO-Guide.html

https://blog.csdn.net/huithe/article/details/7484606

python-property、__get__、__set__的更多相关文章

  1. python的__get__、__set__、__delete__(1)

    内容:    描述符引导        摘要        定义和介绍        描述符协议        调用描述符        样例        Properties        函数和 ...

  2. python 面向对象专题(八):特殊方法 (一)__get__、__set__、__delete__ 描述符(一)

    https://www.cnblogs.com/flashBoxer/p/9771797.html 实现了 __get__.__set__ 或 __delete__ 方法的类是描述符.描述符的用法是, ...

  3. python 面向对象专题(十一):特殊方法 (四)__get__、__set__、__delete__ 描述符(四)描述符用法建议

    使用特性以保持简单 内置的 property 类创建的其实是覆盖型描述符,__set__ 方法和__get__ 方法都实现了,即便不定义设值方法也是如此. 特性的__set__ 方法默认抛出 Attr ...

  4. python 面向对象专题(九):特殊方法 (二)__get__、__set__、__delete__ 描述符(二)覆盖型与非覆盖型描述符对比

    前言 根据是否定义__set__ 方法,描述符可分为两大类. 实现 __set__ 方法的描述符属于覆盖型描述符,因为虽然描述符是类属性,但是实现 __set__ 方法的话,会覆盖对实例属性的赋值操作 ...

  5. python描述符(descriptor)、属性(property)、函数(类)装饰器(decorator )原理实例详解

     1.前言 Python的描述符是接触到Python核心编程中一个比较难以理解的内容,自己在学习的过程中也遇到过很多的疑惑,通过google和阅读源码,现将自己的理解和心得记录下来,也为正在为了该问题 ...

  6. python 3全栈开发-面向对象之绑定方法(classmethod与staticmethod的区别)、多态、封装的特性property

    一.面向对象绑定方法 一.类中定义的函数分成两大类 1.绑定方法(绑定给谁,谁来调用就自动将它本身当作第一个参数传入): 1. 绑定到类的方法:用classmethod装饰器装饰的方法. 为类量身定制 ...

  7. python基础-abstractmethod、__属性、property、setter、deleter、classmethod、staticmethod

    python基础-abstractmethod.__属性.property.setter.deleter.classmethod.staticmethod

  8. 【Python】__slots__ 、@property、多重继承、定制类、枚举类、元类

    __slots__ @property 多重继承 定制类 枚举类 元类 [使用__slots__] 1.动态语言的一个特点就是允许给实例绑定任意的方法和变量,而静态语言(例如Java)必须事先将属性方 ...

  9. 第7.26节 Python中的@property装饰器定义属性访问方法getter、setter、deleter 详解

    第7.26节 Python中的@property装饰器定义属性访问方法getter.setter.deleter 详解 一.    引言 Python中的装饰器在前面接触过,老猿还没有深入展开介绍装饰 ...

随机推荐

  1. 利用maven开发springMVC项目(二)——框架配置

    申明:主要内容来源于大神博客(使用IntelliJ IDEA开发SpringMVC网站(二)框架配置),我只是用eclipse自己练习使用,记录下来也只是为了学习使用,没有任何的商业用途,侵权必删. ...

  2. 【星云测试】开发者测试(2)-采用精准测试工具对J2EE Guns开发框架进行测试

    配置测试Guns Guns简介 Guns是一个近几年来基于SpringBoot的开源便利且较新的JavaEE项目开发框架,它整合了springmvc + shiro + mybatis-plus + ...

  3. Vcenter虚拟化三部曲----VMWare ESXi 5.5安装及配置

    VMWare ESXi 5.5安装大概过程如下:制作虚拟化ESXi系统的USB启动盘,安装ESXi系统到USB,用USB启动ESXi系统.比较难理解,下面图解过程. 下载UNetbootin   (下 ...

  4. thinkpad T61 Fn功能键的完整说明及有关问题解决

    FN键的作用Fn 键是一个组合键,它自己本身没有用,需要和其他功能键组合起来以迅速改变操作特征,它可以组合的键在键盘上都用蓝色标注,具体作用为: Fn+F2:锁定计算机显示器.要再次打开计算机显示器, ...

  5. 多种移动平均计算总结(MA,EMA,SMA,DMA,TMA,WMA)

    多种移动平均计算总结 股票期货里面经常会遇到这些公式,通达信,同花顺,文华,基本都有.作为一个程序员觉得网上比较的思路不清晰,在此做个总结,一目了然. 一.函数简介 MA(x,n)-移动平均,是最简单 ...

  6. hiveSql常见错误记录

    1. In strict mode, if ORDER BY is specified, LIMIT must also be specified. 这个错误提示是因为在hive下写的sql使用了or ...

  7. 双硬盘双系统win10+manjaro-kde搭建

    电脑sdd+hdd双硬盘,默认win10装在了sdd分区,uefi+gpt引导.现在想要在hdd中划分出一个分区安装manjaro,并在开机多重引导. 1. 制作安装盘 先去下载最新的镜像,最好在国内 ...

  8. sql for xml path 处理

    1.将下列结果集 做成 aa   语文,数学 bb    英语,语文 这种格式 使用 for xml  path  记得去重复 WITH cte AS(SELECT stu.studentname,c ...

  9. Sql主从同步服务

    主服务器A:192.168.1.102从服务器B:192.168.1.103 先关掉主服务器phpstudy,把数据库备份到从服务器 1.授权用户:在A服务器新建一个从账号锁定IP GRANT REP ...

  10. hive在客户机启动时出现的问题

    运行环境:一拖一分布式集群+客户端 mysql和hive安装在客户机上 问题:在客户机终端启动hive时出现如下问题: 目前还没有找出是什么原因! 解决办法: 参照http://dblab.xmu.e ...