# -*- coding:utf-8 -*-
#由於方法二存在弊端,建議使用方法一
#方法一
class A:
def __init__(self):
print("A class initialization")
def f1(self):
print("A class -> f1 function")
def f2(self):
print("A class -> f2 function")
class B:
def __init__(self):
self._obj = A()
def f2(self):
print("B class -> f2 function")
#__getattr__() 實際是一個後備方法,只有在屬性不存在時纔會調用。
# 因此,如果代理類實例本身有這個屬性的話,那麼不會觸發這個方法的。
def __getattr__(self, name):
return getattr(self._obj, name)
#方法二: 代理模式
class Proxy:
def __init__(self, obj):
self._obj = obj
def __getattr__(self, name):
print("Proxy class -> __getattr__ function")
return getattr(self._obj, name)
def __setattr__(self, name, value):
print("Proxy class -> __setattr__ function")
if name.startswith('_'):
super().__setattr__(name, value)
else:
setattr(self._obj, name, value)
def __delattr__(self, name):
print("Proxy class -> __delattr__ function")
if name.startswith('_'):
super().__delattr__(name)
else:
delattr(self._obj, name)
class C:
def __init__(self, a):
#注意使用Proxy作爲代理時,被代理類(如C)的屬性的名字不能設置爲
#下劃線開頭的,如果設置爲下劃線開頭的屬性名字,則所有的操作都
#屬於代理類(如Proxy),這些操作不會被應用到被代理類(如C)中
self.a = a
def main():
obj1 = B()
obj1.f2()
obj1.f1()
obj2 = C(10)
p = Proxy(obj2)
print("C class a value: {0}. Proxy class a value: {1}".format(obj2.a, p.a))
p.a = 20
print("C class a value: {0}. Proxy class a value: {1}".format(obj2.a, p.a))
if __name__ == "__main__":
main()
運行結果:
A class initialization
B class -> f2 function
A class -> f1 function
Proxy class -> __setattr__ function
Proxy class -> __getattr__ function
C class a value: 10. Proxy class a value: 10
Proxy class -> __setattr__ function
Proxy class -> __getattr__ function
C class a value: 20. Proxy class a value: 20