当前位置: 首页 > news >正文

学做网站论坛vip教程晋中市科技馆网站建设

学做网站论坛vip教程,晋中市科技馆网站建设,做网站用盗版PS,茶网站源码描述符描述符也是面向进阶的一种#xff0c;由于它的涉及比较广#xff0c;所以单独讲。 一、描述符 描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()中的一个,这也被称为描述符协议。 描述符的作用是用来代理另外一个类的属性#xf… 描述符描述符也是面向进阶的一种由于它的涉及比较广所以单独讲。 一、描述符 描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()中的一个,这也被称为描述符协议。 描述符的作用是用来代理另外一个类的属性必须把描述符定义成一个类的类属性不能定义到构造函数中。 描述符分为两种一种是数据描述符至少实现了__get__()和__set__()另一种是非数据描述符没有实现__set__()。 1.描述符格式 class Foo: #在python3中任何类都是新式类,它只要实现了三种方法之一,那么这个类就被称作一个描述符def __get__(self, instance, owner): #调用一个属性时触发passdef __set__(self, instance, value): #为一个属性赋值时触发passdef __delete__(self, instance): #采用del删除属性时触发pass 2.描述符的使用 描述符该如何使用呢具体代码如下 class Foo: #描述符def __get__(self, instance, owner):print(我是get方法)def __set__(self, instance, value):print(我是set方法)def __delete__(self, instance):print(我是delete方法) class Bar:x Foo() #把描述符代理一个类的属性def __init__(self,n): self.x nb1 Bar(10) b1.x 11111 b1.x del b1.x 执行代码结果为 我是set方法 我是set方法 我是get方法 我是delete方法 可以看出在实例化时也会触发__set__方法因为在类Bar的初始化函数中self.x是被描述符代理的属性。那么对象b1中的属性字典中到底存不存在x这个值呢具体代码如下所示 class Foo(): #描述符def __get__(self, instance, owner):print(我是get方法)def __set__(self, instance, value):print(我是set方法)def __delete__(self, instance):print(我是delete方法) class Bar:x Foo()def __init__(self,n): self.x nb1 Bar(10) print(b1.__dict__) b1.x 11111 print(b1.__dict__) 执行结果为 我是set方法 {} 我是set方法 {} 这是什么情况无论是实例化操作还是赋值操作在对象b1的属性字典中仍然为空。正是因为描述符的关系它相当于把被描述符的类的调用属性操作、赋值操作、删除操作都赋予另一个类来实现跟本身类并没有关系当然这关系到优先级的问题。 3.描述符的优先级 我们要严格遵守优先级类属性数据描述符实例属性非数据描述符找不到的属性触发__getattr__()。 1我们先对类属性数据描述符进行分析具体代码如下 class Foo():def __get__(self, instance, owner):print(我是get方法)def __set__(self, instance, value):print(我是set方法)def __delete__(self, instance):print(我是delete方法) class Bar:x Foo()Bar.x111 print(Bar.x) #结果为111 上述代码打印结果仍为111并没有执行数据描述符是因为Bar类调用了本来要被描述符代理的属性x进行了修改。所有类属性的优先级比数据描述符高。 2数据描述符实例属性的分析代码如下 class Foo():def __get__(self, instance, owner):print(我是get方法)def __set__(self, instance, value):print(我是set方法)def __delete__(self, instance):print(我是delete方法) class Bar:x Foo()b1 Bar() b1.x #结果为我是get方法 b1.x 111 #结果为我是set方法 上述代码Foo类被定义成Bar类的类属性即对Bar类进行实例化实例属性只执行数据描述符的方法。说明了数据描述符的优先级高于实例属性。 3实例属性非数据描述符的分析代码如下 class Foo():def __get__(self, instance, owner):print(我是get方法) class Bar:x Foo()b1 Bar() b1.x 111 print(b1.__dict__) #结果为{x: 111} 上述代码可以看出实例给自己属性进行赋值操作可以在实例的属性字典中找到这说明了实例属性的优先级高于非数据描述符。 4非数据描述符找不到的属性触发__getattr__()的分析代码如下 class Foo():def __get__(self, instance, owner):print(我是get方法) class Bar:x Foo()def __getattr__(self, item):print(我是getattr方法) b1 Bar() b1.x #结果为我是get方法 b1.name #结果为我是getattr方法 上述代码可以看出找得到时触发__get__方法找不到就会触发__getattr__方法。说明了非数据描述符的优先级高于找不到的属性触发__getattr__()。 4.描述符的应用 描述符可以应用到哪些场合呢我们就来举个例子通过描述符机制来实现参数的赋值类型限制。即 class Typed:def __init__(self,key,expected_type):self.key keyself.expected_type expected_typedef __get__(self, instance, owner):print(get方法)return instance.__dict__[self.key]def __set__(self, instance, value):print(set方法)if not isinstance(value,self.expected_type):raise TypeError(你传入的类型不是%s %self.expected_type)instance.__dict__[self.key] valuedef __delete__(self, instance):print(delete方法)instance.__dict__.pop(self.key) class People:name Typed(name,str)age Typed(age,int)salary Typed(salary,float)def __init__(self,name,age,salary):self.name nameself.age ageself.salary salaryp1 People(alex,18,6666.66) p2 People(250,26,4568.55) #不符合赋值类型抛出异常 上述代码对象p1是满足参数的赋值类型所以会触发三次__set__方法。而对象p2不符合赋值类型就会抛出异常。 5.propetry 一个静态属性property本质就是实现了__get____set____delete__三种方法。 propetry有两种用法第一种即 class Foo:property #静态属性def AAA(self):print(get的时候运行)AAA.setterdef AAA(self,value):print(set的时候运行,value)AAA.deleterdef AAA(self):print(delete的时候运行) f1 Foo() f1.AAA f1.AAAaaa del f1.AAA 执行结果为 get的时候运行 set的时候运行 aaa delete的时候运行 上述代码中只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter。 第二种用法的代码实现如下 class Foo:def get_AAA(self):print(get的时候运行)def set_AAA(self,value):print(set的时候运行,value)def del_AAA(self):print(delete的时候运行)AAA property(get_AAA,set_AAA,del_AAA) #内置property三个参数与get,set,delete一一对应 f1 Foo() f1.AAA f1.AAAaaa del f1.AAA 执行结果为 get的时候运行 set的时候运行 aaa delete的时候运行 上述两种用法的结果都是一样的。 我们也可以利用描述符自定制property实现延时计算。我们先对一段代码进行分析来看看我们利用描述符自定制property该如何实现相同的目的。即 class Room:def __init__(self,name,width,length):self.name nameself.width widthself.length lengthproperty #areaproperty(area)def area(self):return self.width*self.length r1 Room(别墅,15,16) print(r1.area) #结果为240 在上述代码中property相当于实现了areaproperty(area)而property它是一个类这是不是相当于property类定义成Room类的类属性这不就是描述符的性质吗它既然是描述符那么它是数据描述符还是非数据描述符呢从结果它打印实例属性可以看出它是非数据描述符因为实例属性的优先级非数据描述符。假如我们自定制property不采用内置的静态属性property该如何实现上述代码即 class Lazyproperty:def __init__(self,func):self.func funcdef __get__(self, instance, owner):return self.func(instance) #instance实例本身 class Room:def __init__(self,name,width,length):self.name nameself.width widthself.length lengthLazyproperty #areaLazyproperty(area)def area(self):return self.width*self.length r1 Room(别墅,15,16) print(r1.area) #结果为240 上述代码中的Lazyproperty是我自定制的当然Lazyproperty类中我们只能定义成非数据描述符否则不会执行area方法。 我们继续利用自定制property来实现延时计算功能 class Lazyproperty:def __init__(self,func):self.func funcdef __get__(self, instance, owner):print(get)if instance is None: #被类调用必须写否则报错因为类没有实例return selfres self.func(instance) #instance实例本身setattr(instance,self.func.__name__,res) #缓存return res class Room:def __init__(self,name,width,length):self.name nameself.width widthself.length lengthLazyproperty #areaLazyproperty(area)def area(self):return self.width*self.length r1 Room(别墅,15,16) print(r1.area) #从字典里先找因为实例属性非数据描述符没有再去类的中找,然后出发了area的__get__方法 print(r1.area) #先从自己的属性字典找,找到了,是上次计算的结果,这样就不用每执行一次都去计算 上述代码实现了延时计算功能这样这不会每次都打印get的操作。描述符是可以实现大部分python类特性中的底层魔法,包括classmethod,staticmethd,property甚至是__slots__属性。  6.类的装饰器 类的装饰器与函数的装饰器性质是一样的类的装饰器分为无参装饰器和有参装饰器。 我们先来定义一个无参的装饰器即 def deco(func):print()func.x 1func.y 2return func deco #相当于Foo deco(Foo) class Foo:pass print(Foo.__dict__) 执行结果为 {__module__: __main__, __dict__: attribute __dict__ of Foo objects, __weakref__: attribute __weakref__ of Foo objects, __doc__: None, x: 1, y: 2} 上述代码当程序遇到deco就马上执行了Foodeco(Foo)可以在结果可以看出Foo类中的属性字典中有键值对x与y。 下面我们来介绍有参的装饰器该如何定义 def Typed(**kwargs):def deco(obj):for key,val in kwargs.items():setattr(obj,key,val)return objreturn decoTyped(x1,y2,z3) #1.Typed(x1,y2,z3)---deco 2.deco-----Foodeco(Foo) class Foo:pass print(Foo.__dict__)Typed(namealex) #deco----Bardeco(Bar) class Bar:pass print(Bar.name) 执行的结果为 {__module__: __main__, __dict__: attribute __dict__ of Foo objects, __weakref__: attribute __weakref__ of Foo objects, __doc__: None, x: 1, y: 2, z: 3} alex 上述代码定义了有参的装饰器函数Typed是用来接收所有参数的。 下面我们利用装饰器的应用以及描述符来实现参数的赋值类型限制即 class Typed:def __init__(self,key,expected_type):self.key keyself.expected_type expected_typedef __get__(self, instance, owner):print(get方法)return instance.__dict__[self.key]def __set__(self, instance, value):print(set方法)if not isinstance(value,self.expected_type):raise TypeError(你传入的类型不是%s %self.expected_type)instance.__dict__[self.key] valuedef __delete__(self, instance):print(delete方法)instance.__dict__.pop(self.key)def deco(**kwargs):def wrapper(obj):for key,val in kwargs.items():setattr(obj,key,Typed(key,val)) #Typed(key,val)描述符return objreturn wrapperdeco(name str,age int,salary float) class People:def __init__(self,name,age,salary):self.name nameself.age ageself.salary salaryp1 People(alex,20,6666.66) 实例化时触发了三次__set__方法。在描述符里也规定了参数的赋值类型。 转载于:https://www.cnblogs.com/lzc69/p/11316469.html
http://www.yutouwan.com/news/171174/

相关文章:

  • j建设银行信用卡网站wordpress 插件 破解
  • 做网站价钱怎么查看网站谁做的
  • 周口seo 网站企业网站备案名称窍门
  • 广州黄埔区网站建设m开头的网站开发工具
  • 网站开发好要租服务器吗网页设计图片的边框怎么做
  • 怎样推广自己的产品余姚seo智能优化
  • 海口网站建设流程网站建设預算
  • 海诚网站建设广州网站建设推广
  • 可以做 描文本链接的网站有哪个网站可以学做吃的
  • 如何自建网站入口企业网站的推广形式有
  • 外贸建站与推广做网站加入广告联盟
  • 菜鸟建网站定制网站建设服务商
  • 洛阳网红乐陵seo
  • 厦门做网站优化电子商务市场营销
  • 漳州找人做网站要求哪些wordpress页面点赞
  • txt做网站如何加图片wordpress不能更改邮箱
  • 企业站seo湖南seo网站开发
  • 从化建网站新手做电商卖什么好
  • 西安网站开发定制制作wordpress评论框样式
  • 一流的龙岗网站制作wordpress资源付费
  • 免费wap自助建站火星建站卖农产品最好的平台
  • 中国糕点网页设计网站佛山企业网站建设平台
  • 网站开发哪些专业outlook WordPress设置
  • 自学做网站要多久网站推广行业赚钱吗
  • html5 jsp做网站可以么wordpress和ss一起
  • 论坛网站模板免费下载自己做网站怎么维护
  • 中元建设网站网站开发视频播放无画面
  • 做平面资源比较好的网站扮家家室内设计
  • 品牌服装网站源码医疗器械生产许可证
  • dw网页制作三个页面跳转关键词优化举例