前言

  描述符是用于代理另一个类的属性,一般用于大型的框架中,在实际的开发项目中较少使用,本质是一个实现了__get__(),__set__(),__delete__()其中一个方法的新式类

  __get__():调用一个属性时执行

  __set__():属性赋值时执行

  __delete__():采用del删除属性时触发

  描述符实现@property

  描述符实现@classmethod

  描述符实现@staticmethod

示例

#描述符
class test:
def __get__(self, instance, owner):
print('---get方法') def __set__(self, instance, value):
print('---set方法') def __delete__(self, instance):
print('---delete方法') class test2:
name = test()#描述符代理了test2类里的name属性 t1 = test2()
#调用了被描述符代理的属性,执行__get__()方法
t1.name #---get方法
#赋值了被描述符代理的属性,执行__set__()方法
t1.name = 1 #---set方法
#赋值了被描述符代理的属性,执行__delete__()方法
del t1.name #---delete方法

属性查找的优先级

  1.类属性

  2.数据描述符(同时实现了__get__()和__set__()方法)

  3.实例属性

  4.非数据描述符(没有实现__set__()方法)

  5.找不到的属性执行__getattr__()

#非数据描述符
class test:
def __get__(self, instance, owner):
print('get方法') class test2:
name = test()#描述符代理了test2类里的name属性 t1 = test2()
#在实例对象里中创建了name属性,并赋值chen
t1.name = 'chen'
print(t1.__dict__) #{'name': 'chen'}

利用描述符实现赋值类型限制(一)

#数据描述符
class Typed:
def __init__(self,key,value_type):
self.key = key
self.value_type = value_type def __get__(self, instance, owner):
print('get方法')
return instance.__dict__[self.key] def __set__(self, instance, value):
print('set方法')
if not isinstance(value,self.value_type): #判断类型
raise TypeError('传入的类型不是',self.value_type)
instance.__dict__[self.key] = value def __delete__(self, instance):
print('delete方法')
instance.__dict__.pop(self.key) class People:
name = Typed('name',str) #数据描述符代理属性
age = Typed('age',int) #数据描述符代理属性 def __init__(self,name,age):
self.name = name #赋值操作,执行__set__方法
self.age = age #测试
p1 = People('chen',21)
print(p1.__dict__) #{'name': 'chen', 'age': 21} p1 = People('chen','21') #报错:TypeError: ('传入的类型不是', <class 'int'>)

利用描述符和装饰器实现赋值类型限制(二)

#数据描述符
class Typed:
def __init__(self,key,value_type):
self.key = key
self.value_type = value_type def __get__(self, instance, owner):
print('get方法')
return instance.__dict__[self.key] def __set__(self, instance, value):
print('set方法')
if not isinstance(value,self.value_type): #判断类型
raise TypeError('传入的类型不是',self.value_type)
instance.__dict__[self.key] = value def __delete__(self, instance):
print('delete方法')
instance.__dict__.pop(self.key) #限制赋值类型的装饰器
def deco(**kwargs):
def warapper(obj):
for key,val in kwargs.items(): setattr(obj,key,Typed(key,val)) #在装饰器中给类属性实现描述符代理 return obj
return warapper @deco(name=str,age=int) #@wrapper ===>People=wrapper(People)
class People:
#使用装饰器取代了以下两步
# name = Typed('name',str) #数据描述符代理属性
# age = Typed('age',int) #数据描述符代理属性
def __init__(self,name,age):
self.name = name #赋值操作,执行__set__方法
self.age = age #测试
p1 = People('chen',21)
'''
输出:
set方法
set方法
'''
print(p1.__dict__) #{'name': 'chen', 'age': 21}

描述符实现@property

class Demoproperty:
def __init__(self,func):
print('----+')
self.func = func class People:
def __init__(self,name,age):
self.name = name #赋值操作,执行__set__方法
self.age = age @Demoproperty #eat=Demoproperty(eat)
def eat(self):
print("%s在吃饭"%self.name) p1 =People('chen',21)
p1.eat.func(p1) #chen在吃饭

瞎搞

#非数据描述符
class Demoproperty:
def __init__(self,func):
self.func = func def __get__(self, instance, owner):
print('get')
res = self.func(instance)
return res class People: def __init__(self,name,age):
self.name = name #赋值操作,执行__set__方法
self.age = age #实现了添加描述符的操作
@Demoproperty #eat=Demoproperty(eat)
def eat(self):
print("%s在吃饭"%self.name) p1 =People('chen',21)
p1.eat #chen在吃饭

描述符实现@calssmethod

classmethod 修饰符对应的函数不需要实例化,不需要 self 参数,但第一个参数需要是表示自身类的 cls 参数,可以来调用类的属性,类的方法,实例化对象等  

class ClassMethod:
def __init__(self,func):
self.func=func def __get__(self, instance, owner): #owner是类
def feedback(*args,**kwargs): return self.func(owner,*args,**kwargs) return feedback #返回一个可以传参的方法 class People: @ClassMethod # say_hi=ClassMethod(say_hi)
def say_hi(cls,name,age):
print('我是%s,年龄%s' %(name,age)) People.say_hi('chen',21) #我是chen,年龄21

描述符实现@staticmethod

class StaticMethod:
def __init__(self,func):
self.func=func def __get__(self, instance, owner): #owner是类
def feedback(*args,**kwargs): return self.func(*args,**kwargs) return feedback #返回一个可以传参的方法 class People: @StaticMethod # say_hi=ClassMethod(say_hi)
def say_hi(name,age):
print('我是%s,年龄%s' %(name,age)) People.say_hi('chen',21) #我是chen,年龄21

 

python之路(11)描述符的更多相关文章

  1. 如何正确地使用Python的属性和描述符

    关于@property装饰器 在Python中我们使用@property装饰器来把对函数的调用伪装成对属性的访问. 那么为什么要这样做呢?因为@property让我们将自定义的代码同变量的访问/设定联 ...

  2. python高级编程之描述符与属性03

    # -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' #属性Property #提供了一个内建描述符类型,它知道如何将一个 ...

  3. python高级编程之描述符与属性02

    # -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' #元描述符 #特点是:使用宿主类的一个或者多个方法来执行一个任务,可 ...

  4. Python 为什么要使用描述符?

    学习 Python 这么久了,说起 Python 的优雅之处,能让我脱口而出的, Descriptor(描述符)特性可以排得上号. 描述符 是Python 语言独有的特性,它不仅在应用层使用,在语言的 ...

  5. Python中属性和描述符的简单使用

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

  6. 流畅的python第二十章属性描述符学习记录

    描述符是对多个属性运用相同存取逻辑的一种方式.例如,Django ORM 和 SQL Alchemy等 ORM 中的字段类型是描述符,把数据库记录中字段里的数据与 Python 对象的属性对应起来.描 ...

  7. 90% 的 Python 开发者不知道的描述符应用

    经过上面的讲解,我们已经知道如何定义描述符,且明白了描述符是如何工作的. 正常人所见过的描述符的用法就是上篇文章提到的那些,我想说的是那只是描述符协议最常见的应用之一,或许你还不知道,其实有很多 Py ...

  8. Python进阶——什么是描述符?

    本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 在 Python 开发中,你可能听说过「描述符」这个概念,由于我们很少直接使用它,所以大部分开发人员 ...

  9. python基础学习之描述符和装饰器

    描述符的了解: 描述符协议: python描述符是一个"绑定行为"的对象属性,在描述符协议中,它可以通过方法重写属性的访问.这些方法有: __get__, __set__, 和__ ...

  10. 【python之路11】集合数据类型(set)

    集合数据类型(set):集合是不重复的无需序列 1.集合数据类型的创建 a = {11,22,33} #或 a = set() #创建空集合,不能用a={},这样创建的是字典类型 2.集合转换(将可迭 ...

随机推荐

  1. EntityFramework Code-First—领域类配置之DataAnnotations

    本文出自:https://www.cnblogs.com/tang-tang/p/5510574.html 一.摘要 EF Code-First提供了一个可以用在领域类或其属性上的DataAnnota ...

  2. EntityFramework Core进行读写分离最佳实践方式,了解一下(二)?

    前言 写过上一篇关于EF Core中读写分离最佳实践方式后,虽然在一定程度上改善了问题,但是在评论中有的指出更换到从数据库,那么接下来要进行插入此时又要切换到主数据库,同时有的指出是否可以进行底层无感 ...

  3. zoj 3601

    链接 [https://vjudge.net/contest/293343#problem/B] 题意 就是n男m女.然后给出他们喜欢那些人 再给出q次询问 每次参加party的人 让你找出某个人满足 ...

  4. 《为大量出现的KPI流快速部署异常检测模型》 笔记

    以下我为这篇<Rapid Deployment of Anomaly Detection Models for Large Number of Emerging KPI Streams>做 ...

  5. HTML、CSS、JS中常用的东西在IE中兼容问题汇总

    1.因为国内360浏览器.QQ浏览器等更新较快,所以不考虑Chrome支持某个css与否,因为一般都支持. 2.因为火狐等使用的人较少,且更新较快,所以不考虑支持与否,因为一般都支持 3.主要就是汇总 ...

  6. MySQL 的数据目录

    MySQL里面有4个数据库是属于MySQL自带的系统数据库: mysql 这个数据库贼核心,它存储了MySQL的用户账户和权限信息,一些存储过程.事件的定义信息,一些运行过程中产生的日志信息,一些帮助 ...

  7. webpack4 学习 --- 处理静态资源

    webpack 是利用loader 来处理各种资源的,wepback的配置基本上就是为各种资源文件,指定不同类型的loader. 1,处理css 最基本的css 处理loader 是css-loade ...

  8. 在access转sql server指定的转换无效

    今天继续昨天没解决的问题,还是继续报错数据库中“指定的转换无效”,看着这个错误都有点头大了,啊啊啊啊,因为无法再代码中寻找到具体点,只好在晚上继续查询 最后终于看到一条帖子说在转换的时候可能出现数据冲 ...

  9. icns图标的制作

    1. 准备一张无损的png图片(1024x1024) 2. 新建一个文件夹 必须要以iconset为后缀 $ mkdir hgl_pngpic.iconset 3. 使用sips 命令剪切10个不一样 ...

  10. HDU1166-ZKW树

    单点修改,区间求和 // // Created by helica on 2018/3/18. // //zkw #include <cstdio> #include <cstrin ...