python学习深水区,仅供自己参考
# 类型检查的描述器
class Typed:
#变量名称,期待的数据类型
def __init__(self, name, expected_type):
self.name = name
self.expected_type = expected_type
#获取字典里的变量名称
def __get__(self, instance, cls):
if instance is None:
return self
else:
return instance.__dict__[self.name]
#设置变量,如果不符合期望类型抛出异常
def __set__(self, instance, value):
if not isinstance(value, self.expected_type):
raise TypeError('Expected ' + str(self.expected_type))
instance.__dict__[self.name] = value
#删除变量
def __delete__(self, instance):
del instance.__dict__[self.name]
# Class decorator that applies it to selected attributes
# 类型检查的描述器
def typeassert(**kwargs):
#{'name': <class 'str'>, 'shares': <class 'int'>, 'price': <class 'float'>}
def decorate(cls):
for name, expected_type in kwargs.items():
# Attach a Typed descriptor to the class
# 给这个类添加一个类型描述器
setattr(cls, name, Typed(name, expected_type))
return cls
return decorate
# 描述器应用样例
@typeassert(name=str, shares=int, price=float)
class Stock:
def __init__(self, name, shares, price):
self.name = name
self.shares = shares
self.price = price
def __str__(self):
return 'name=,{},shares={},price={}'.format(self.name,self.shares,self.price)
#延迟计算属性
#将一个只读属性定义成一个property,只在访问的时候才会计算结果
#一旦被访问,结果将会缓存起来,不用每次计算
#定义延迟属性的方法是通过描述器类@lazyproperty
class lazyproperty:
def __init__(self,func):
self.func=func
def __get__(self,instance,cls):
if instance is None:
return self
else:
value=self.func(instance)
setattr(instance,self.func.__name__,value)
return value
import math
#惰性描述器实例
class Circle:
def __init__(self,radius):
self.radius=radius
@lazyproperty
def area(self):
print('Computing area')
return math.pi*self.radius**2
@lazyproperty
def perimeter(self):
print('Computing perimeter')
return 2*math.pi*self.radius
# 属性的代理访问
# 一个被代理的类
class A:
def __init__(self):
print('class A init')
def fun1(self,x):
print('class A func1 ')
return x
def fun2(self,x):
print('class A func2 ')
return x
# 实现代理的类
class B1:
#简单代理
def __init__(self):
self._a=A()
def fun1(self,x):
print('proxy class B1 func1')
return self._a.fun1(x)
def fun2(self,x):
print('proxy class B1 func2')
return self._a.fun2(x)
def fun3(self,x):
print('proxy class B1 func3')
# 大量的方法需要代理
class B2:
#使用__getattr__的代理,代理方法比较多的时候
def __init__(self):
self._a=A()
def fun3(self,x):
print('proxy class B2 func3')
def __getattr__(self, name):
#这个方法在访问的 attribute 不存在的时候被调用
print('B2 getattr')
return getattr(self._a,name)
#实现代理模式
class B3:
def __init__(self,obj):
self._obj=obj
def __getattr__(self, name):
print('getattr:',name)
return getattr(self._obj,name)
def __setattr__(self, name, value):
if name.startswith('_'):
super().__setattr__(name,value)
else:
print('setattr:', name)
setattr(self._obj,name,value)
def __delattr__(self, name):
if name.startswith('_'):
super().__delattr__(name)
else:
print('delattr:', name)
delattr(self._obj,name)
if __name__ == '__main__':
stock1=Stock('stocktest',2,10.2)
#--------------------
#初始化时的顺序
#先执行@typeassert(name=str, shares=int, price=float)
#再执行函数typeassert,进行参数传递
#再执行Typed.__init__,进行参数名和参数类型初始化
#--------------------
#执行时的顺序
#先执行stock.__init__
#再执行Typed.__set__
print(stock1)
#name=,stocktest,shares=2,price=10.2
#stock2 = Stock('stocktest', 2.2, 10.2)
#TypeError: Expected <class 'int'>
#---------------------
#延迟描述器
#先扫描Circle类中的@lazyproperty的函数
#再执行lazyproperty.__init__,进行初始化
c=Circle(4)
print(c.radius)
print(c.area)
# Computing area
# 50.26548245743669
print(c.perimeter)
# Computing perimeter
# 25.132741228718345
print(c.area)
# 50.26548245743669
print(c.perimeter)
# 25.132741228718345
# -------------------------
#几种代理机制
b=B1()
b.fun1(11)
# proxy class B1 func1
# class A func1
b.fun2(12)
# proxy class B1 func2
# class A func2
b.fun3(13)
# proxy class B1 func3
b = B2()
b.fun1(21)
# B2 getattr
# class A func1
b.fun2(22)
# B2 getattr
# class A func2
b.fun3(23)
# proxy class B2 func3
a=A() #class A init
p=B3(a)
print(p.fun1(21)) #getattr: fun1 class A func1 #21
print(p.fun2(3)) #getattr: fun2 class A func2 3
要
本文分享自 python与大数据分析 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!