<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>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ## 問題 在子類中,你想要擴展定義在父類中的property的功能。 ## 解決方案 考慮如下的代碼,它定義了一個property: class Person: def __init__(self, name): self.name = name # Getter function @property def name(self): return self._name # Setter function @name.setter def name(self, value): if not isinstance(value, str): raise TypeError('Expected a string') self._name = value # Deleter function @name.deleter def name(self): raise AttributeError("Can't delete attribute") 下面是一個示例類,它繼承自Person并擴展了 `name` 屬性的功能: class SubPerson(Person): @property def name(self): print('Getting name') return super().name @name.setter def name(self, value): print('Setting name to', value) super(SubPerson, SubPerson).name.__set__(self, value) @name.deleter def name(self): print('Deleting name') super(SubPerson, SubPerson).name.__delete__(self) 接下來使用這個新類: >>> s = SubPerson('Guido') Setting name to Guido >>> s.name Getting name 'Guido' >>> s.name = 'Larry' Setting name to Larry >>> s.name = 42 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "example.py", line 16, in name raise TypeError('Expected a string') TypeError: Expected a string >>> 如果你僅僅只想擴展property的某一個方法,那么可以像下面這樣寫: class SubPerson(Person): @Person.name.getter def name(self): print('Getting name') return super().name 或者,你只想修改setter方法,就這么寫: class SubPerson(Person): @Person.name.setter def name(self, value): print('Setting name to', value) super(SubPerson, SubPerson).name.__set__(self, value) ## 討論 在子類中擴展一個property可能會引起很多不易察覺的問題,因為一個property其實是 `getter`、`setter` 和 `deleter` 方法的集合,而不是單個方法。因此,但你擴展一個property的時候,你需要先確定你是否要重新定義所有的方法還是說只修改其中某一個。 在第一個例子中,所有的property方法都被重新定義。在每一個方法中,使用了 `super()` 來調用父類的實現。在 `setter` 函數中使用 `super(SubPerson, SubPerson).name.__set__(self, value)` 的語句是沒有錯的。為了委托給之前定義的setter方法,需要將控制權傳遞給之前定義的name屬性的 `__set__()` 方法。不過,獲取這個方法的唯一途徑是使用類變量而不是實例變量來訪問它。這也是為什么我們要使用 `super(SubPerson, SubPerson)` 的原因。 如果你只想重定義其中一個方法,那只使用 @property 本身是不夠的。比如,下面的代碼就無法工作: class SubPerson(Person): @property # Doesn't work def name(self): print('Getting name') return super().name 如果你試著運行會發現setter函數整個消失了: >>> s = SubPerson('Guido') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "example.py", line 5, in __init__ self.name = name AttributeError: can't set attribute >>> 你應該像之前說過的那樣修改代碼: class SubPerson(Person): @Person.getter def name(self): print('Getting name') return super().name 這么寫后,property之前已經定義過的方法會被復制過來,而getter函數被替換。然后它就能按照期望的工作了: >>> s = SubPerson('Guido') >>> s.name Getting name 'Guido' >>> s.name = 'Larry' >>> s.name Getting name 'Larry' >>> s.name = 42 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "example.py", line 16, in name raise TypeError('Expected a string') TypeError: Expected a string >>> 在這個特別的解決方案中,我們沒辦法使用更加通用的方式去替換硬編碼的 `Person` 類名。如果你不知道到底是哪個基類定義了property,那你只能通過重新定義所有property并使用 `super()` 來將控制權傳遞給前面的實現。 值的注意的是上面演示的第一種技術還可以被用來擴展一個描述器(在8.9小節我們有專門的介紹)。比如: # A descriptor class String: def __init__(self, name): self.name = name def __get__(self, instance, cls): if instance is None: return self return instance.__dict__[self.name] def __set__(self, instance, value): if not isinstance(value, str): raise TypeError('Expected a string') instance.__dict__[self.name] = value # A class with a descriptor class Person: name = String('name') def __init__(self, name): self.name = name # Extending a descriptor with a property class SubPerson(Person): @property def name(self): print('Getting name') return super().name @name.setter def name(self, value): print('Setting name to', value) super(SubPerson, SubPerson).name.__set__(self, value) @name.deleter def name(self): print('Deleting name') super(SubPerson, SubPerson).name.__delete__(self) 最后值的注意的是,讀到這里時,你應該會發現子類化 `setter` 和 `deleter` 方法其實是很簡單的。這里演示的解決方案同樣適用,但是在 [Python的issue頁面](http://bugs.python.org/issue14965) 報告的一個bug,或許會使得將來的Python版本中出現一個更加簡潔的方法。
                  <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>

                              哎呀哎呀视频在线观看