Python基础第22天
一:描述符的应用
众所周知,python是弱类型语言,即参数的赋值没有类型限制,下面我们通过描述符机制来实现类型限制功能
class Typed: def __init__(self,key,expected_type): self.key=key self.expected_type=expected_type def __get__(self, instance, owner): print('get方法') # print('instance参数【%s】'%instance) # print('owner参数【%s】'%owner) return instance.__dict__[self.key] def __set__(self, instance, value): print('set方法') # print('instance参数【%s】'%instance) # print('value参数【%s】' % value) # print('====>',self) if not isinstance(value,self.expected_type): # print('你传入的类型不是字符串,错误') # return raise TabError('%s 你传入的类型不是%s'%(self.key,self.expected_type)) instance.__dict__[self.key]=value def __delete__(self, instance): # print('delete方法') # print('instance参数【%s】' % instance) instance.__dict__.pop(self.key) class People: name=Typed('name',str) #描述符 age=Typed('name',int) def __init__(self,name,age,salary): self.name=name #触发代理 self.age=age self.salary=salary p1=People(123,13,13.3) print(p1.__dict__) p1=People(123,18,13.3) print(p1.__dict__) p1.name print(p1.name) print(p1.__dict__) p1.name='aaa' print(p1.__dict__) print(p1.__dict__) del p1.name print(p1.__dict__)
二:类的装饰器
def deco(func): print('============') return func @deco #test=deco(test) def test(): print('test函数运行') test()
@deco #语法糖修饰类 Foo=deco(Foo)
class Foo:
pass
============
test函数运行
============
def deco(obj): print('============',obj) obj.x=1 obj.y=2 obj.z=3 return obj @deco #Foo=deco(Foo) class Foo: pass print(Foo.__dict__) def deco(obj): print('============',obj) obj.x=1 obj.y=2 obj.z=3 return obj @deco #Foo=deco(Foo) def test(): print('test函数运行') test.x=1 test.y=1 print(test.__dict__) #验证了一切皆对象
类的装饰器修订版: 操作类属性
def Typed(**kwargs): def deco(obj): # print('--->',kwargs) # print('类名---》',obj) for key,val in kwargs.items(): # obj.__dict__[key]=val setattr(obj,key,val) return obj print('==>',kwargs) return deco @Typed(x=1,y=2,z=3) #Typed(x=1,y=2,z=3)---->deco @deco---->Foo=deco(Foo) class Foo: pass print(Foo.__dict__) @Typed(name='egon') class Bar: pass print(Bar.name) #egon
class Typed: def __init__(self,key,expected_type): self.key=key self.expected_type=expected_type def __get__(self, instance, owner): print('get方法') # print('instance参数【%s】'%instance) # print('owner参数【%s】'%owner) return instance.__dict__[self.key] def __set__(self, instance, value): print('set方法') # print('instance参数【%s】'%instance) # print('value参数【%s】' % value) # print('====>',self) if not isinstance(value,self.expected_type): # print('你传入的类型不是字符串,错误') # return raise TabError('%s 你传入的类型不是%s'%(self.key,self.expected_type)) instance.__dict__[self.key]=value def __delete__(self, instance): # print('delete方法') # print('instance参数【%s】' % instance) instance.__dict__.pop(self.key) def deco(**kwargs): #kwargs={'name':str,'age':int} def wrapper(obj): #obj=People for key,val in kwargs.items(): #(('name',str),('age',int)) setattr(obj,key,Typed(key,val)) #People.name=Typed('name',str) return obj return wrapper @deco(name=str,age=int) #@wrapper====》People=wrapper(People) class People: # name=Typed('name',str) #调用 # age=Typed('age',int) def __init__(self,name,age,salary,gender,height): self.name=name self.age=age self.salary=salary p1=People('yyy',13,13.3,'x','y') print(People.__dict__)
描述符是可以实现大部分python类特性中的底层魔法,包括@classmethod,@staticmethd,@property甚至是__slots__属性
利用描述符原理完成一个自定制@property,实现延迟计算(本质就是把一个函数属性利用装饰器原理做成一个描述符:类的属性字典中函数名为key,value为描述符类产生的对象)
class Room: def __init__(self,name,width,length): self.name=name self.width=width self.length=length @property def area(self): return self.width * self.length r1=Room('alex',1,1) print(r1.area) @property回顾
class Lazyproperty: def __init__(self,func): print('--------->',func) self.func=func def __get__(self, instance, owner): print(instance) return self.func(instance) class Room: def __init__(self,name,width,length): self.name=name self.width=width self.length=length # @property #cal_area=property(cal_area) @Lazyproperty #为room增加描述符,cal_area被Lazyproperty代理 实例化 cal_area=func def cal_area(self): return self.width * self.length r1=Room('厕所',100,100) print(r1.cal_area)
class Foo: @property def AAA(self): print('get的时候运行') @AAA.setter def AAA(self,val): print('set的时候运行',val) @AAA.deleter def AAA(self): print('del的时候运行') f1=Foo() f1.AAA f1.AAA='aaa' del f1.AAA