收集了网上的三个例子,然后做了些注释:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
class Wrapper:
def __init__(self, obj):
self.wrapper = obj
print self.wrapper
print type(self.wrapper)
print"-"*100
def __getattr__(self, item):
print("trace:", item)
return getattr(self.wrapper, item)
if __name__ == '__main__':
x = Wrapper([1, 2, 3, 4])
x.append(35)
x.remove(2)
print(x.wrapper) # [1,3,4,35]
- 在
__init__(self,obj)
方法中传入一个被委托对象。 - 通过重写
__getattr__(self,item)
方法,拦截外部对象的属性调用 -
在
__getattr__(self,item)
中,将拦截到的属性,让被委托对象去使用。python 中的属性概念,和Java中的属性概念是不同的。Java中的属性,就是指类中定义的成员变量,绝对不包含方法。而在python中,任何能以
obj.xx
形式调用的东西,全部可以称为属性。无论是方法,还是变量,还是对象。
所以上述代码中调用x.append(N)
,实际上是让x的属性wrapper
去调用append(N)
方法。
上面传入的参数是[1,2,3,4]
,是一个list
类型的对象,该对象自然可以调用append
remove
这些方法。
http://blog.csdn.net/DucklikeJAVA/article/details/73729212
---------------------------------------------------------------------------------------------------------------
#-*- encoding:utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
class A:
def f_one(self, x):
print"here is f_one"
print"x=",x
print"-"*100
def f_two(self):
print"here is f_two"
print"-"*100
class B(A):
def __init__(self):
self._a = A()#也就是说在类B中有个成员变量例化了类A,_a是A的对象,不要太在意_a这个奇怪的名字
def f_one(self, x):
return self._a.f_one(x)
def f_two(self):
return self._a.f_two()
def f_three(self):
print"Here is B(A)"
if __name__ == '__main__':
b_test=B()
x=6
b_test.f_one(x)
b_test.f_two()
这就是一个最简单的委托,将A的实例在B类中生成,并且转化为B的一个私有属性,当我们需要访问A的属性的时候,加入我们只暴露B出来,这时候就只能通过B类来访问A类,这就达到了委托的效果。
上面的这种方法使用情景为:有几个方法需要委托,当我们需要大量委托的时候这显然不是一个好办法,这时候还有另一个更巧妙的方法:getattr()方法,下面请看代码:
#-*- encoding:utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
class A:
def f_one(self, x):
print"here is f_one"
print"x=",x
print"-"*100
def f_two(self):
print"here is f_two"
print"-"*100
class B(A):
def __init__(self):
self._a = A()
def f_three(self):
pass
def __getattr__(self, name):#相当于重写了__getattr__,利用__getattr_来实现委托的效果(其实委托就是甩锅的意思啦,B搞不定,甩锅给A)
return getattr(self._a, name)
if __name__ == '__main__':
b_test=B()
x=6
b_test.f_one(x)
b_test.f_two()
这里要注意一下这个新的方法,这个方法的作用是用来查找所有的属性,放在这里时,如果代码中尝试访问这个类中不存在的属性时,会去调用实例_a中的属性,这样就可以实现大量的代理。