>[success] # 委托访问 ~~~ 1.在一个类里中的属性是另一个类的对象,然后调用另一个类中的内容 ~~~ >[danger] ##### 最简单的委托访问 ~~~ 1.使用的范围只能用在配委托对象,方法比较少的时候 ~~~ ~~~ class A: def spam(self, x): pass def foo(self): pass class B: """简单的代理""" def __init__(self): self._a = A() def spam(self, x): # Delegate to the internal self._a instance return self._a.spam(x) def foo(self): # Delegate to the internal self._a instance return self._a.foo() def bar(self): pass ~~~ >[danger] ##### 利用__getattr__ 代理 ~~~ 1.在类中定义好__getattr__,__getattr__用来查找所有属性,如果没有访问的对象没有这个属性,执行中的参数name 获取的 是未定义参数 2.getattr 会讲两个参数进行拼接如下文档讲解,拼接后返回a的方法 def getattr(object, name, default=None): # known special case of getattr """ getattr(object, name[, default]) -> value Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y. When a default argument is given, it is returned when the attribute doesn't exist; without it, an exception is raised in that case. """ pass 3.下面使用b.foo()在委托的对象中并没有也就是B类中没有这个方法,然而会执行__getattr__ 去使用getattr,调用找到a 4.getattr 方法如果所拼接的方法A中也没有会异常报错 ~~~ ~~~ class A: def spam(self, x): pass def foo(self): pass class B: """使用__getattr__的代理,代理方法比较多时候""" def __init__(self): self._a = A() def bar(self): pass # Expose all of the methods defined on class A def __getattr__(self, name): """这个方法在访问的attribute不存在的时候被调用 the __getattr__() method is actually a fallback method that only gets called when an attribute is not found""" return getattr(self._a, name) b = B() b.bar() b.foo() ~~~ >[danger] ##### 其他代理模式 ~~~ # A proxy class that wraps around another object, but # exposes its public attributes class Proxy: def __init__(self, obj): self._obj = obj # Delegate attribute lookup to internal obj def __getattr__(self, name): print('getattr:', name) return getattr(self._obj, name) # Delegate attribute assignment def __setattr__(self, name, value): if name.startswith('_'): super().__setattr__(name, value) else: print('setattr:', name, value) setattr(self._obj, name, value) # Delegate attribute deletion def __delattr__(self, name): if name.startswith('_'): super().__delattr__(name) else: print('delattr:', name) delattr(self._obj, name) ~~~ * 使用 ~~~ class Spam: def __init__(self, x): self.x = x def bar(self, y): print('Spam.bar:', self.x, y) # Create an instance s = Spam(2) # Create a proxy around it p = Proxy(s) # Access the proxy print(p.x) # Outputs 2 p.bar(3) # Outputs "Spam.bar: 2 3" p.x = 37 # Changes s.x to 37 ~~~