描述器实现:
class A:
def __init__(self,data):
print('A.init')
self.a1 = data
def __get__(self,instance,owner):
print('A.__get__',self,instance,owner)
return self
def __set__(self, instance, value):
print('A.__set__',self,instance,value)
class B:
x = A('abc')
def __init__(self):
print('B.init')
self.x= A(123)
b = B()
print('===========================')
print(B.x.a1)
print('===========================')
print(b.x.a1)
print('===========================')
b.x=A(345)
print(B.x.a1)
print('===========================')
print(b.__dict__)
print(B.__dict__)
print('===========================')
运行结果:
A.init
B.init
A.init
A.__set__ <__main__.A object at 0x7ffbf44fb390> <__main__.B object at 0x7ffbf2fbe160> <__main__.A object at 0x7ffbf2fbe2e8>
===========================
A.__get__ <__main__.A object at 0x7ffbf44fb390> None <class '__main__.B'>
abc
===========================
A.__get__ <__main__.A object at 0x7ffbf44fb390> <__main__.B object at 0x7ffbf2fbe160> <class '__main__.B'>
abc
===========================
A.init
A.__set__ <__main__.A object at 0x7ffbf44fb390> <__main__.B object at 0x7ffbf2fbe160> <__main__.A object at 0x7ffbf2fbe2e8>
A.__get__ <__main__.A object at 0x7ffbf44fb390> None <class '__main__.B'>
abc
===========================
{}
{'__dict__': <attribute '__dict__' of 'B' objects>, '__weakref__': <attribute '__weakref__' of 'B' objects>, '__init__': <function B.__init__ at 0x7ffbf44eabf8>, 'x': <__main__.A object at 0x7ffbf44fb390>, '__doc__': None, '__module__': '__main__'}
==========================
改造成staticmethod和classmethod装饰器:(非数据描述器):
from functools import partial
class StaticMethod:
def __init__(self, fn):
print(1,fn)
self.fn = fn
def __get__(self, instance, owner):
print(self,instance,owner)
return self.fn
class ClassMethod:
def __init__(self, fn):
print(fn)
self.fn = fn
def __get__(self, instance, owner):
print(self,instance,owner)
#return self.fn(owner)
return partial(self.fn,owner)
class A:
@StaticMethod
def foo():
print('static')
@ClassMethod
def bar(cls):
print(cls.__name__)
f1 = A.foo
print(2,f1)
f1()
print('==================================')
f2 = A.bar
print(3,f2)
f2()
运行结果:
1 <function A.foo at 0x7fb10a77d2f0>
<function A.bar at 0x7fb10a77d378>
<__main__.StaticMethod object at 0x7fb10bd090f0> None <class '__main__.A'>
2 <function A.foo at 0x7fb10a77d2f0>
static
==================================
<__main__.ClassMethod object at 0x7fb10bd09390> None <class '__main__.A'>
3 functools.partial(<function A.bar at 0x7fb10a77d378>, <class '__main__.A'>)
A
描述器+装饰器+反射的综合案例:
class A:
def __init__(self,name):
self.name = name
def __get__(self, instance, owner):
print('__get__')
return instance.__dict__['name']
def __set__(self, instance, value):
print('__set__')
instance.__dict__['name'] = value
class C:
def __init__(self,cls):
self.cls = cls
def __call__(self, name):
setattr(self.cls,'name',A(name))
return self.cls(name)
@C
class B:
# name = A('tom')
def __init__(self,name):
self.name = name
b = B('kangkang')
print('=============================')
print(b.name)
print('=============================')
b.name = 'jerry'
print('=============================')
print(b.name)
print('=============================')
print(b.__dict__)
运行结果:
__set__
=============================
__get__
kangkang
=============================
__set__
=============================
__get__
jerry
=============================
{'name': 'jerry'}
改进:(为传参进行检查是否符合注解类型)---------解决python是强类型语言传参的问题
class Typed:
def __init__(self,key,type):
self.type = type
self.key = key
def __get__(self, instance, owner):
return instance.__dict__[self.key]
def __set__(self, instance, value):
if not isinstance(value,self.type):
raise ValueError(value)
instance.__dict__[self.key] = value
import inspect
class TypeAssert:
def __init__(self,cls):
self.cls = cls
def __call__(self, name, age):
params = inspect.signature(self.cls).parameters
for key,param in params.items():
if param.annotation != param.empty:
setattr(self.cls, key, Typed(key,param.annotation))
return self.cls(name,age)
@TypeAssert
class Person: #Person = TypeAssert(Person)
def __init__(self,name:str,age:int):
self.name = name
self.age = age
p1 = Person('tom',19) #TypeAssert(Person)('tom',18)
print(p1.name)
print(p1.age)
print('============================================')
p1 = Person('Jerry','20')
运行结果:
tom
19
============================================
File "/home/yzx/PycharmProjects/python/t58.py", line 38, in <module>
p1 = Person('Jerry','20')
File "/home/yzx/PycharmProjects/python/t58.py", line 25, in __call__
return self.cls(name,age)
File "/home/yzx/PycharmProjects/python/t58.py", line 31, in __init__
self.age = age
File "/home/yzx/PycharmProjects/python/t58.py", line 11, in __set__
raise ValueError(value)
ValueError: 20
自我实现property属性装饰器
class Property:
def __init__(self, fget, fset=None):
self.fget = fget
self.fset = fset
def __get__(self, instance, owner):
if instance is not None:
return self.fget(instance)
return self
def __set__(self, instance, value):
if callable(self.fset):
self.fset(instance, value)
else:
raise AttributeError()
def setter(self, fset):
self.fset = fset
return self
class A:
def __init__(self, data):
self._data = data
@Property
def data(self):
return self._data
@data.setter
def data(self, value):
self._data = value
a = A(100)
print(a.data)
a.data = 200
print(a.data)
运行结果:
100
200