面向对象进阶
面向对象进阶
一 、上下文协同管理(__enter__和 __exit__)
# class Foo: # def __init__(self,name): # self.name = name # def __enter__(self): # print('执行enter',self) # return self # def __exit__(self, exc_type, exc_val, exc_tb): # print('执行exit') # print(exc_type) # print(exc_val) # print(exc_tb) # # with Foo('a.txt') as f: # 相当于f = obj.__enter__() ## with时触发enter # print('------') # print('=====') # print('000000') ### 上面的代码块执行完毕时触发exit ## 没有异常时,with 下的代码块运行完毕,自动触发exit,exc_type, exc_val, exc_tb三个参数均为None # class Foo: # def __init__(self,name): # self.name = name # def __enter__(self): # print('执行enter',self) # return self # def __exit__(self, exc_type, exc_val, exc_tb): # print('执行exit') # print(exc_type) # print(exc_val) # print(exc_tb) # # with Foo('a.txt') as f: # 相当于f = obj.__enter__() ## with时触发enter # print('------') # print(sdhf) ## 异常 # print('=====') # print('000000') ## 有异常时,到异常那句代码,直接触发、__exit__,此时三个参数为 # exc_type <class 'NameError'>; # exc_val name 'sdhf' is not defined ### exc_tb <traceback object at 0x0000000002203148> class Foo: def __init__(self,name): self.name = name def __enter__(self): print('执行enter',self) return self def __exit__(self, exc_type, exc_val, exc_tb): print('执行exit') print(exc_type) print(exc_val) print(exc_tb) return True with Foo('a.txt') as f: # 相当于f = obj.__enter__() ## with时触发enter print('------') print(sdhf) ## 异常 print('=====') print('000000') ## 有异常,但是exit返回值为True时,会吞掉异常,遇到异常那句代码,执行exit,然后开始执行with外面的代码 # 好处 #1.使用with语句的目的就是把代码放在with中执行,with结束后,自动完成清理工作,无需手动干预 #2.在需要管理一些资源,比如文件,网络连接,和锁的编程环境中,可以在__exit__中定制自动释放资源的机制。
二 、描述符的应用
场景:为下面People类传入的属性加上限制类型
#只为name限定输入类型 # class Typed: # def __init__(self,key): # self.key =key # 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) # if not isinstance(value,str): # raise TypeError('输入的不是字符串') # instance.__dict__[self.key] = value # def __delete__(self, instance): # print('执行delete') # instance.__dict__.pop(self.key) # # class People: # name = Typed('name') # def __init__(self,name,age,salay): # self.name = name # self.age = age # self.salay = salay # p1 =People('goulonghui',18,1500000.56) # print(p1.name) # print(p1.__dict__) ## {'name': 'goulonghui', 'age': 18, 'salay': 1500000.56} # # p1.name = '苟陇辉' # print(p1.__dict__) ## {'name': '苟陇辉', 'age': 18, 'salay': 1500000.56} # # del p1.name # print(p1.__dict__) ## {'age': 18, 'salay': 1500000.56} # # p1 = People(1855,18,1555555.56) ## TypeError: 输入的不是字符串 ## 为name,和age 同时限定输入类型 # class Typed: # def __init__(self,key): # self.key =key # 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) # if self.key == 'name': # if not isinstance(value,str): # raise TypeError('输入的不是字符串') # instance.__dict__[self.key] = value # if self.key == 'age': # if not isinstance(value,int): # raise TypeError('输入的不是数字') # instance.__dict__[self.key] = value # # def __delete__(self, instance): # print('执行delete') # instance.__dict__.pop(self.key) # # class People: # name = Typed('name') # age = Typed('age') # def __init__(self,name,age,salay): # self.name = name # self.age = age # self.salay = salay # p1 =People('goulonghui',18,1500000.56) # print(p1.name) # print(p1.__dict__) ## {'name': 'goulonghui', 'age': 18, 'salay': 1500000.56} ## 为name,和age 同时限定输入类型 class Typed: def __init__(self,key,except_type): self.key =key self.except_type = except_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) if not isinstance(value,self.except_type): raise TypeError('%s传入的类型不是%s'%(self.key,self.except_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,salay): self.name = name self.age = age self.salay = salay p1 = People('goulonghui',18,154965896.5) print(p1.__dict__) ##{'name': 'goulonghui', 'age': 18, 'salay': 154965896.5} # p1 = People(56,18,154965896.5) ### TypeError: name传入的类型不是<class 'str'> p1 = People('goulonghui','18',154965896.5) ## TypeError: age传入的类型不是<class 'int'>
三、类的装饰器
def deco(obj): # print('======') # obj.x = 1 # obj.y = 2 # obj.z = 3 # return obj # # @deco ## 相当于 Foo = deco(Foo) # class Foo: # pass # # print(Foo.__dict__) ### 'x': 1, 'y': 2, 'z': 3}
def typed(**kwargs): print(kwargs) def deco(obj): print(kwargs) for key,val in kwargs.items(): setattr(obj,key,val) return obj return deco @typed(x=1,y=2) ### 拆成@ 和 typed(x=1,y=2)两部分----->deco----->@deco------>Foo = deco(Foo) class Foo: pass print(Foo.__dict__) ## 'x': 1, 'y': 2} @typed(name = 'goulonghui') class Bar: pass print(Bar.name) ### goulonghui
class Typed: def __init__(self,key,except_type): self.key = key self.except_type = except_type def __get__(self, instance, owner): return instance.__dict__[self.key] def __set__(self, instance, value): # print(instance) # print(value) if not isinstance(value,self.except_type): raise TypeError('%s传入的类型不是%s'%(self.key,self.except_type)) instance.__dict__[self.key] = value def __delete__(self, instance): instance.__dict__.pop(self.key) def deco(**kwargs): def wapper(obj): for key,val in kwargs.items(): setattr(obj,key,Typed(key,val)) return obj return wapper @deco(name = str,age = int) ## deco(name = str,age = int)----->@wapper----->obj = wapper(obj) class People: def __init__(self, name, age, salay): self.name = name self.age = age self.salay = salay print(People.__dict__) p1 = People('goulognhui',20,566666666) print(p1.__dict__)
四、利用描述符自定制property
# class Lazyproperty: # def __init__(self,func): # self.func = func # def __get__(self, instance, owner): # print('get') # print(instance) # print(owner) # if instance == None: ## 此情况为类调用时,直接返回一个对象(area就是Lazyproperty实例化产生的一个对象) # return self # return self.func(instance) # # class Room: # # @Lazyproperty ## area = Lazyproperty(area) 相当于area = Lazyproperty()Room的类属性area被Lazyproperty代理了 # def __init__(self,name,length,width,height): # self.name = name # self.length = length # self.width = width # self.height = height # @Lazyproperty ## area = Lazyproperty(area),实例化Lazyproperty, area是Lazyproperty的一个对象 # def area(self): # return self.length * self.width # # r1 = Room('WC',1,1,1) # # 实例调用 # print(r1.area) # print(r1.__dict__) # print(Room.__dict__) ## 'area': <__main__.Lazyproperty object at 0x00000000027B9B38>, # # # 模拟系统property,用类调用area时,返回一个property对象 # # 类调用 # print(Room.area) ### <__main__.Lazyproperty object at 0x0000000001E89B70>
class Lazyproperty: def __init__(self,func): self.func = func def __get__(self, instance, owner): print('get') print(instance) print(owner) if instance == None: ## 此情况为类调用时,直接返回一个对象(area就是Lazyproperty实例化产生的一个对象) return self res = self.func(instance) setattr(instance,self.func.__name__,res) #将计算的结果加在属性字典中,(self.func.__name__是拿到func(即area)函数名) return res class Room: # @Lazyproperty ## area = Lazyproperty(area) 相当于area = Lazyproperty()Room的类属性area被Lazyproperty代理了 def __init__(self,name,length,width,height): self.name = name self.length = length self.width = width self.height = height @Lazyproperty ## area = Lazyproperty(area),实例化Lazyproperty, area是Lazyproperty的一个对象 def area(self): return self.length * self.width r1 = Room('WC',1,1,1) print(r1.area) ## 第一次为res的值 print(r1.area) print(r1.area) ### 后面2次都是在实例属性字典中拿‘area',
五、property的其他写法
# class Foo: # def __init__(self,age): # self.age = age # @property # def name(self): # print('get') # # @name.setter # def name(self,val): # print(self,val) # @name.deleter # def name(self): # print('del') # # f1 = Foo(18) # f1.name 触发get_name # f1.name = 'goulognhui' # 触发set_name # del f1.name ##触发del_name
class Foo: def __init__(self,age): self.age = age def get_name(self): print('get') def set_name(self,val): print(self,val) def del_name(self): print('del') name = property(get_name,set_name,del_name) #利用property内置方法做 f1 = Foo(18) f1.name# 触发get_name f1.name = 'goulognhui' # 触发set_name del f1.name ##触发del_name
六、元类
# 元类:产生类的类是元类,type # class Foo: # pass # print(Foo) ## <class '__main__.Foo'> # # # def __init__(): # pass # FFo = type('FFo',(object,),{'x':1,'init':__init__}) # print(FFo) ## <class '__main__.Foo'> ## ------自定制元类--------- class Mytype(type): def __init__(self,a,b,c): print('元类在执行') def __call__(self, *args, **kwargs): obj = object.__new__(self) ## 产生一个Foo的实例f1 self.__init__(obj,*args,**kwargs) ### 给obj(即f1)设值,即调用Foo里的init初始化函数 return obj class Foo(metaclass=Mytype): ## 相当于Mytype(self,'Foo',(object,),{})实例化产生Foo类,执行元类的init函数 def __init__(self,name): ### 这里的self 为Foo的实例f1 self.name = name f1 = Foo('苟陇辉') print(f1.__dict__)
学无止境!

浙公网安备 33010602011771号