<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 問題 你想將某個實例的屬性訪問代理到內部另一個實例中去,目的可能是作為繼承的一個替代方法或者實現代理模式。 ## 解決方案 簡單來說,代理是一種編程模式,它將某個操作轉移給另外一個對象來實現。最簡單的形式可能是像下面這樣: class A: def spam(self, x): pass def foo(self): pass class B1: """簡單的代理""" 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 如果僅僅就兩個方法需要代理,那么像這樣寫就足夠了。但是,如果有大量的方法需要代理,那么使用 `__getattr__()` 方法或許或更好些: class B2: """使用__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) `__getattr__` 方法是在訪問attribute不存在的時候被調用,使用演示: b = B() b.bar() # Calls B.bar() (exists on B) b.spam(42) # Calls B.__getattr__('spam') and delegates to A.spam 另外一個代理例子是實現代理模式,例如: # 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 通過自定義屬性訪問方法,你可以用不同方式自定義代理類行為(比如加入日志功能、只讀訪問等)。 ## 討論 代理類有時候可以作為繼承的替代方案。例如,一個簡單的繼承如下: class A: def spam(self, x): print('A.spam', x) def foo(self): print('A.foo') class B(A): def spam(self, x): print('B.spam') super().spam(x) def bar(self): print('B.bar') 使用代理的話,就是下面這樣: class A: def spam(self, x): print('A.spam', x) def foo(self): print('A.foo') class B: def __init__(self): self._a = A() def spam(self, x): print('B.spam', x) self._a.spam(x) def bar(self): print('B.bar') def __getattr__(self, name): return getattr(self._a, name) 當實現代理模式時,還有些細節需要注意。首先,`__getattr__()` 實際是一個后備方法,只有在屬性不存在時才會調用。因此,如果代理類實例本身有這個屬性的話,那么不會觸發這個方法的。另外,`__setattr__()` 和 `__delattr__()` 需要額外的魔法來區分代理實例和被代理實例 `_obj` 的屬性。一個通常的約定是只代理那些不以下劃線 `_` 開頭的屬性(代理類只暴露被代理類的公共屬性)。 還有一點需要注意的是,`__getattr__()` 對于大部分以雙下劃線(__)開始和結尾的屬性并不適用。比如,考慮如下的類: class ListLike: """__getattr__對于雙下劃線開始和結尾的方法是不能用的,需要一個個去重定義""" def __init__(self): self._items = [] def __getattr__(self, name): return getattr(self._items, name) 如果是創建一個ListLike對象,會發現它支持普通的列表方法,如append()和insert(),但是卻不支持len()、元素查找等。例如: >>> a = ListLike() >>> a.append(2) >>> a.insert(0, 1) >>> a.sort() >>> len(a) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: object of type 'ListLike' has no len() >>> a[0] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'ListLike' object does not support indexing >>> 為了讓它支持這些方法,你必須手動的實現這些方法代理: class ListLike: """__getattr__對于雙下劃線開始和結尾的方法是不能用的,需要一個個去重定義""" def __init__(self): self._items = [] def __getattr__(self, name): return getattr(self._items, name) # Added special methods to support certain list operations def __len__(self): return len(self._items) def __getitem__(self, index): return self._items[index] def __setitem__(self, index, value): self._items[index] = value def __delitem__(self, index): del self._items[index] 11.8小節還有一個在遠程方法調用環境中使用代理的例子。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看