标签:定制 缓存 递归 int cte 计算 blank obb ext
__enter__和__exit__
数据描述符:至少实现__get__,__set__方法的
非数据描述符:没有__set__方法的
上下文管理协议(with语句)改写,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法。
# -*- coding: utf-8 -*-
class Open:
def __init__(self,name):
self.name=name
def __enter__(self):
print(‘出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量‘)
# return self
def __exit__(self, exc_type, exc_val, exc_tb):
print(‘with中代码块执行完毕时执行我啊‘)
with Open(‘b.txt‘) as f:
print(‘=====>执行代码块‘)
# print(f,f.name)
# -*- coding: utf-8 -*-
class Open:
def __init__(self,name):
self.name=name
def __enter__(self):
print(‘出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量‘)
def __exit__(self, exc_type, exc_val, exc_tb):
print(‘with中代码块执行完毕时执行我啊‘)
#下面三个ext执行完毕就代表with代码块里的语句执行完毕,出现异常,下面的代码不再执行
print(exc_type) #异常类型
print(exc_val) #异常值
print(exc_tb) #追溯信息
with Open(‘b.txt‘) as f: #触发__enter__
print(‘=====>执行代码块‘)
raise AttributeError(‘***着火啦,救火啊***‘)
print(‘0‘*100) #------->不会执行
用途:
1.使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预
2.在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制
描述符应用
控制输入类型
# -*- coding: utf-8 -*-
class Typed:
def __init__(self,key):
self.key=key
def __get__(self,instance,owner):
print(‘get方法‘)
# print(‘isinstance参数;‘,isinstance)
# print(‘owner参数;‘,owner)
return instance.__dict__[self.key]
def __set__(self,instance,value):
print(‘set方法‘)
# print(‘isinstance参数;‘,instance)
# print(‘owner参数;‘,value)
#通过初始化函数写活了
if not isinstance(value,str):
print(‘输入不是字符串‘)
else:
instance.__dict__[self.key]=value
def __delete__(self,instance):
print(‘delete方法‘)
# print(‘isinstance参数;‘, instance)
instance.__dict__.pop(self.key)
class people:
name=Typed(‘name‘)
# age=Typed(‘age‘)
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary
p1=people("bob",22,5000)
p1.name
print(p1.__dict__) #没有name属性,他被数据描述符代理了
del p1.name
print(p1.__dict__)
p2=people(1,22,5000)
进一步改进
# -*- coding: utf-8 -*-
class Typed:
def __init__(self,key,expected_type):
self.key=key
self.expected_type=expected_type
def __get__(self,instance,owner):
# print(‘get方法‘)
# print(‘isinstance参数;‘,isinstance)
# print(‘owner参数;‘,owner)
return instance.__dict__[self.key]
def __set__(self,instance,value):
# print(‘set方法‘)
# print(‘isinstance参数;‘,instance)
# print(‘owner参数;‘,value)
#通过初始化函数写活了
if not isinstance(value,self.expected_type):
print(‘输入不是%s‘%self.expected_type)
else:
instance.__dict__[self.key]=value
def __delete__(self,instance):
print(‘delete方法‘)
# print(‘isinstance参数;‘, instance)
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=name
self.age=age
self.salary=salary
p1=people("bob",22,5000.0)
p1.name
print(p1.__dict__) #没有name属性,他被数据描述符代理了
del p1.name
print(p1.__dict__)
p2=people(1,22,5000.0)
类的装饰器
初级(没有参数):
# -*- coding: utf-8 -*-
def decorate(cls):
print(‘类的装饰器开始运行啦------>‘)
return cls
@decorate #无参:People=decorate(People)
class People:
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary
print(self.age,self.name,self.salary)
p1=People(‘egon‘,18,3333.3)
------------恢复内容开始------------
__enter__和__exit__
数据描述符:至少实现__get__,__set__方法的
非数据描述符:没有__set__方法的
上下文管理协议(with语句)改写,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法。
# -*- coding: utf-8 -*-
class Open:
def __init__(self,name):
self.name=name
def __enter__(self):
print(‘出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量‘)
# return self
def __exit__(self, exc_type, exc_val, exc_tb):
print(‘with中代码块执行完毕时执行我啊‘)
with Open(‘b.txt‘) as f:
print(‘=====>执行代码块‘)
# print(f,f.name)
# -*- coding: utf-8 -*-
class Open:
def __init__(self,name):
self.name=name
def __enter__(self):
print(‘出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量‘)
def __exit__(self, exc_type, exc_val, exc_tb):
print(‘with中代码块执行完毕时执行我啊‘)
#下面三个ext执行完毕就代表with代码块里的语句执行完毕,出现异常,下面的代码不再执行
print(exc_type) #异常类型
print(exc_val) #异常值
print(exc_tb) #追溯信息
with Open(‘b.txt‘) as f: #触发__enter__
print(‘=====>执行代码块‘)
raise AttributeError(‘***着火啦,救火啊***‘)
print(‘0‘*100) #------->不会执行
用途:
1.使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预
2.在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制
描述符应用
控制输入类型
# -*- coding: utf-8 -*-
class Typed:
def __init__(self,key):
self.key=key
def __get__(self,instance,owner):
print(‘get方法‘)
# print(‘isinstance参数;‘,isinstance)
# print(‘owner参数;‘,owner)
return instance.__dict__[self.key]
def __set__(self,instance,value):
print(‘set方法‘)
# print(‘isinstance参数;‘,instance)
# print(‘owner参数;‘,value)
#通过初始化函数写活了
if not isinstance(value,str):
print(‘输入不是字符串‘)
else:
instance.__dict__[self.key]=value
def __delete__(self,instance):
print(‘delete方法‘)
# print(‘isinstance参数;‘, instance)
instance.__dict__.pop(self.key)
class people:
name=Typed(‘name‘)
# age=Typed(‘age‘)
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary
p1=people("bob",22,5000)
p1.name
print(p1.__dict__) #没有name属性,他被数据描述符代理了
del p1.name
print(p1.__dict__)
p2=people(1,22,5000)
进一步改进
# -*- coding: utf-8 -*-
class Typed:
def __init__(self,key,expected_type):
self.key=key
self.expected_type=expected_type
def __get__(self,instance,owner):
# print(‘get方法‘)
# print(‘isinstance参数;‘,isinstance)
# print(‘owner参数;‘,owner)
return instance.__dict__[self.key]
def __set__(self,instance,value):
# print(‘set方法‘)
# print(‘isinstance参数;‘,instance)
# print(‘owner参数;‘,value)
#通过初始化函数写活了
if not isinstance(value,self.expected_type):
print(‘输入不是%s‘%self.expected_type)
else:
instance.__dict__[self.key]=value
def __delete__(self,instance):
print(‘delete方法‘)
# print(‘isinstance参数;‘, instance)
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=name
self.age=age
self.salary=salary
p1=people("bob",22,5000.0)
p1.name
print(p1.__dict__) #没有name属性,他被数据描述符代理了
del p1.name
print(p1.__dict__)
p2=people(1,22,5000.0)
类的装饰器
初级(没有参数):
# -*- coding: utf-8 -*-
def decorate(cls):
print(‘类的装饰器开始运行啦------>‘)
return cls
@decorate #无参:People=decorate(People)
class People:
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary
print(self.age,self.name,self.salary)
p1=People(‘egon‘,18,3333.3)
------------恢复内容开始------------
__enter__和__exit__
数据描述符:至少实现__get__,__set__方法的
非数据描述符:没有__set__方法的
上下文管理协议(with语句)改写,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法。
# -*- coding: utf-8 -*-
class Open:
def __init__(self,name):
self.name=name
def __enter__(self):
print(‘出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量‘)
# return self
def __exit__(self, exc_type, exc_val, exc_tb):
print(‘with中代码块执行完毕时执行我啊‘)
with Open(‘b.txt‘) as f:
print(‘=====>执行代码块‘)
# print(f,f.name)
# -*- coding: utf-8 -*-
class Open:
def __init__(self,name):
self.name=name
def __enter__(self):
print(‘出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量‘)
def __exit__(self, exc_type, exc_val, exc_tb):
print(‘with中代码块执行完毕时执行我啊‘)
#下面三个ext执行完毕就代表with代码块里的语句执行完毕,出现异常,下面的代码不再执行
print(exc_type) #异常类型
print(exc_val) #异常值
print(exc_tb) #追溯信息
with Open(‘b.txt‘) as f: #触发__enter__
print(‘=====>执行代码块‘)
raise AttributeError(‘***着火啦,救火啊***‘)
print(‘0‘*100) #------->不会执行
用途:
1.使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预
2.在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制
描述符应用
控制输入类型
# -*- coding: utf-8 -*-
class Typed:
def __init__(self,key):
self.key=key
def __get__(self,instance,owner):
print(‘get方法‘)
# print(‘isinstance参数;‘,isinstance)
# print(‘owner参数;‘,owner)
return instance.__dict__[self.key]
def __set__(self,instance,value):
print(‘set方法‘)
# print(‘isinstance参数;‘,instance)
# print(‘owner参数;‘,value)
#通过初始化函数写活了
if not isinstance(value,str):
print(‘输入不是字符串‘)
else:
instance.__dict__[self.key]=value
def __delete__(self,instance):
print(‘delete方法‘)
# print(‘isinstance参数;‘, instance)
instance.__dict__.pop(self.key)
class people:
name=Typed(‘name‘)
# age=Typed(‘age‘)
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary
p1=people("bob",22,5000)
p1.name
print(p1.__dict__) #没有name属性,他被数据描述符代理了
del p1.name
print(p1.__dict__)
p2=people(1,22,5000)
进一步改进
# -*- coding: utf-8 -*-
class Typed:
def __init__(self,key,expected_type):
self.key=key
self.expected_type=expected_type
def __get__(self,instance,owner):
# print(‘get方法‘)
# print(‘isinstance参数;‘,isinstance)
# print(‘owner参数;‘,owner)
return instance.__dict__[self.key]
def __set__(self,instance,value):
# print(‘set方法‘)
# print(‘isinstance参数;‘,instance)
# print(‘owner参数;‘,value)
#通过初始化函数写活了
if not isinstance(value,self.expected_type):
print(‘输入不是%s‘%self.expected_type)
else:
instance.__dict__[self.key]=value
def __delete__(self,instance):
print(‘delete方法‘)
# print(‘isinstance参数;‘, instance)
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=name
self.age=age
self.salary=salary
p1=people("bob",22,5000.0)
p1.name
print(p1.__dict__) #没有name属性,他被数据描述符代理了
del p1.name
print(p1.__dict__)
p2=people(1,22,5000.0)
类的装饰器
初级(没有参数):
# -*- coding: utf-8 -*-
def decorate(cls):
print(‘类的装饰器开始运行啦------>‘)
return cls
@decorate #无参:People=decorate(People)
class People:
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary
print(self.age,self.name,self.salary)
p1=People(‘egon‘,18,3333.3)
进阶(有参数)
# -*- coding: utf-8 -*-
def typeassert(**kwargs):
def decorate(cls):
print(‘2------>‘)
for key,value in kwargs.items():
setattr(cls,key,value)
return cls
print(‘1------>‘, kwargs)
return decorate
@typeassert() #name=str,age=int,salary=float
#有参:1.运行typeassert(...)返回结果是decorate,此时参数都传给kwargs 2.People=decorate(People)
class People:
pass
# def __init__(self,name,age,salary):
# self.name=name
# self.age=age
# self.salary=salary
print(People.__dict__)
@typeassert(hobby=‘ball‘)
class bar():
pass
#添加了hobby属性
print(bar.__dict__)
可添加不定个数属性的示例:
# -*- coding: utf-8 -*-
class Typed:
def __init__(self,name,expected_type):
self.name=name
self.expected_type=expected_type
def __get__(self, instance, owner):
print(‘get--->‘,instance,owner)
if instance is None:
return self
return instance.__dict__[self.name]
def __set__(self, instance, value):
print(‘set--->‘,instance,value)
if not isinstance(value,self.expected_type):
raise TypeError(‘Expected %s‘ %str(self.expected_type))
instance.__dict__[self.name]=value
def __delete__(self, instance):
print(‘delete--->‘,instance)
instance.__dict__.pop(self.name)
def typeassert(**kwargs):
def decorate(cls):
print(‘类的装饰器开始运行啦------>‘,kwargs)
for name,expected_type in kwargs.items():
setattr(cls,name,Typed(name,expected_type))
return cls
return decorate
@typeassert(name=str,age=int,salary=float)#在此添加要增加的属性
#有参:1.运行typeassert(...)返回结果是decorate,此时参数都传给kwargs 2.People=decorate(People)
class People:
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary
print(People.__dict__)
p1=People(‘egon‘,18,3333.3)
自定制property
装饰器可以是函数,也可以是类类型。
# -*- coding: utf-8 -*-
class Lazyproperty:
def __init__(self,func):
self.func=func
def __get__(self, instance, owner):
print(‘这是我们自己定制的静态属性,r1.area实际是要执行r1.area()‘)
if instance is None:
return self
return self.func(instance) #此时你应该明白,到底是谁在为你做自动传递self的事情
class Room:
def __init__(self,name,width,length):
self.name=name
self.width=width
self.length=length
@Lazyproperty #area=Lazyproperty(area) 相当于定义了一个类属性,即描述符
def area(self):
return self.width * self.length
r1=Room(‘alex‘,1,1)
print(r1.area) #将r1.area传参数写在Lazyproperty中的__get__里
应用:自制property实现延迟计算功能
# -*- coding: utf-8 -*-
class Lazyproperty:
def __init__(self,func):
self.func=func
def __get__(self, instance, owner):
print(‘这是我们自己定制的静态属性,r1.area实际是要执行r1.area()‘)
if instance is None:
return self
else:
print(‘--->‘)
value=self.func(instance)
setattr(instance,self.func.__name__,value) #计算一次就缓存到实例的属性字典中
return value
# 如果加了set,将该非数据描述符变为数据描述符,优先级高于实列属性,缓存能力丧失
# def __set__(self, instance, value):
# print(‘hahahahahah‘)
class Room:
def __init__(self,name,width,length):
self.name=name
self.width=width
self.length=length
@Lazyproperty #area=Lazyproperty(area) 相当于‘定义了一个类属性,即描述符‘
def area(self):
return self.width * self.length
r1=Room(‘alex‘,1,1)
print(r1.area) #先从自己的属性字典找,没有再去类的中找,然后出发了area的__get__方法
print(r1.area) #先从自己的属性字典找,找到了,是上次计算的结果,这样就不用每执行一次都去计算
property补充:一个静态属性property本质就是实现了get,set,delete三种方法
# -*- coding: utf-8 -*-
class Foo:
@property
def AAA(self):
print(‘get的时候运行我啊‘)
@AAA.setter
def AAA(self,value):
print(‘set的时候运行我啊‘)
@AAA.deleter
def AAA(self):
print(‘delete的时候运行我啊‘)
#只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter
f1=Foo()
f1.AAA
f1.AAA=‘aaa‘
del f1.AAA
应用(类型检测)
# -*- coding: utf-8 -*-
class People:
def __init__(self,name):
self.name=name #实例化就触发property
@property
def name(self):
# return self.name #无限递归
print(‘get------>‘)
return self.DouNiWan
@name.setter
def name(self,value):
print(‘set------>‘)
if not isinstance(value,str):
raise TypeError(‘必须是字符串类型‘)
self.DouNiWan=value
@name.deleter
def name(self):
print(‘delete------>‘)
del self.DouNiWan
p1=People(‘alex‘) #self.name实际是存放到self.DouNiWan里
print(p1.name)
print(p1.__dict__)
p1.name=1
元类
所有定义的类都是由type产生的。
# -*- coding: utf-8 -*-
class foo:
pass
print(type(foo))
定义类的两种方法
# -*- coding: utf-8 -*-
class foo:
pass
print(type(foo))
print(foo)
def __init__(self,name,age):
self.name=name
self.age=age
def test(self):
print(‘=======>‘)
Foo=type(‘foo1‘,(object,),{‘x‘:1,‘__init__‘:__init__,‘test‘:test})
print(Foo)
print(Foo.__dict__)
foo_1=Foo(‘alex‘,22)
foo_1.test()
自定义元类(详情查看连接)
标签:定制 缓存 递归 int cte 计算 blank obb ext
原文地址:https://www.cnblogs.com/2018-1025/p/12399387.html