<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 功能強大 支持多語言、二開方便! 廣告
                ## 問題 你想給某個實例attribute增加除訪問與修改之外的其他處理邏輯,比如類型檢查或合法性驗證。 ## 解決方案 自定義某個屬性的一種簡單方法是將它定義為一個property。例如,下面的代碼定義了一個property,增加對一個屬性簡單的類型檢查: class Person: def __init__(self, first_name): self.first_name = first_name # Getter function @property def first_name(self): return self._first_name # Setter function @first_name.setter def first_name(self, value): if not isinstance(value, str): raise TypeError('Expected a string') self._first_name = value # Deleter function (optional) @first_name.deleter def first_name(self): raise AttributeError("Can't delete attribute") 上述代碼中有三個相關聯的方法,這三個方法的名字都必須一樣。第一個方法是一個 `getter` 函數,它使得 `first_name` 成為一個屬性。其他兩個方法給 `first_name` 屬性添加了 `setter` 和 `deleter` 函數。需要強調的是只有在 `first_name` 屬性被創建后,后面的兩個裝飾器 `@first_name.setter` 和 `@first_name.deleter` 才能被定義。 property的一個關鍵特征是它看上去跟普通的attribute沒什么兩樣,但是訪問它的時候會自動觸發 `getter` 、`setter` 和 `deleter` 方法。例如: >>> a = Person('Guido') >>> a.first_name # Calls the getter 'Guido' >>> a.first_name = 42 # Calls the setter Traceback (most recent call last): File "<stdin>", line 1, in <module> File "prop.py", line 14, in first_name raise TypeError('Expected a string') TypeError: Expected a string >>> del a.first_name Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: can't delete attribute >>> 在實現一個property的時候,底層數據(如果有的話)仍然需要存儲在某個地方。因此,在get和set方法中,你會看到對 `_first_name``屬性的操作,這也是實際數據保存的地方。另外,你可能還會問為什么 ``__init__()` 方法中設置了 `self.first_name` 而不是 `self._first_name` 。在這個例子中,我們創建一個property的目的就是在設置attribute的時候進行檢查。因此,你可能想在初始化的時候也進行這種類型檢查。通過設置 `self.first_name` ,自動調用 `setter` 方法,這個方法里面會進行參數的檢查,否則就是直接訪問 `self._first_name` 了。 還能在已存在的get和set方法基礎上定義property。例如: class Person: def __init__(self, first_name): self.set_first_name(first_name) # Getter function def get_first_name(self): return self._first_name # Setter function def set_first_name(self, value): if not isinstance(value, str): raise TypeError('Expected a string') self._first_name = value # Deleter function (optional) def del_first_name(self): raise AttributeError("Can't delete attribute") # Make a property from existing get/set methods name = property(get_first_name, set_first_name, del_first_name) ## 討論 一個property屬性其實就是一系列相關綁定方法的集合。如果你去查看擁有property的類,就會發現property本身的fget、fset和fdel屬性就是類里面的普通方法。比如: >>> Person.first_name.fget <function Person.first_name at 0x1006a60e0> >>> Person.first_name.fset <function Person.first_name at 0x1006a6170> >>> Person.first_name.fdel <function Person.first_name at 0x1006a62e0> >>> 通常來講,你不會直接取調用fget或者fset,它們會在訪問property的時候自動被觸發。 只有當你確實需要對attribute執行其他額外的操作的時候才應該使用到property。有時候一些從其他編程語言(比如Java)過來的程序員總認為所有訪問都應該通過getter和setter,所以他們認為代碼應該像下面這樣寫: class Person: def __init__(self, first_name): self.first_name = name @property def first_name(self): return self._first_name @first_name.setter def first_name(self, value): self._first_name = value 不要寫這種沒有做任何其他額外操作的property。首先,它會讓你的代碼變得很臃腫,并且還會迷惑閱讀者。其次,它還會讓你的程序運行起來變慢很多。最后,這樣的設計并沒有帶來任何的好處。特別是當你以后想給普通attribute訪問添加額外的處理邏輯的時候,你可以將它變成一個property而無需改變原來的代碼。因為訪問attribute的代碼還是保持原樣。 Properties還是一種定義動態計算attribute的方法。這種類型的attributes并不會被實際的存儲,而是在需要的時候計算出來。比如: import math class Circle: def __init__(self, radius): self.radius = radius @property def area(self): return math.pi * self.radius ** 2 @property def diameter(self): return self.radius ** 2 @property def perimeter(self): return 2 * math.pi * self.radius 在這里,我們通過使用properties,將所有的訪問接口形式統一起來,對半徑、直徑、周長和面積的訪問都是通過屬性訪問,就跟訪問簡單的attribute是一樣的。如果不這樣做的話,那么就要在代碼中混合使用簡單屬性訪問和方法調用。下面是使用的實例: >>> c = Circle(4.0) >>> c.radius 4.0 >>> c.area # Notice lack of () 50.26548245743669 >>> c.perimeter # Notice lack of () 25.132741228718345 >>> 盡管properties可以實現優雅的編程接口,但有些時候你還是會想直接使用getter和setter函數。例如: >>> p = Person('Guido') >>> p.get_first_name() 'Guido' >>> p.set_first_name('Larry') >>> 這種情況的出現通常是因為Python代碼被集成到一個大型基礎平臺架構或程序中。例如,有可能是一個Python類準備加入到一個基于遠程過程調用的大型分布式系統中。這種情況下,直接使用get/set方法(普通方法調用)而不是property或許會更容易兼容。 最后一點,不要像下面這樣寫有大量重復代碼的property定義: class Person: def __init__(self, first_name, last_name): self.first_name = first_name self.last_name = last_name @property def first_name(self): return self._first_name @first_name.setter def first_name(self, value): if not isinstance(value, str): raise TypeError('Expected a string') self._first_name = value # Repeated property code, but for a different name (bad!) @property def last_name(self): return self._last_name @last_name.setter def last_name(self, value): if not isinstance(value, str): raise TypeError('Expected a string') self._last_name = value 重復代碼會導致臃腫、易出錯和丑陋的程序。好消息是,通過使用裝飾器或閉包,有很多種更好的方法來完成同樣的事情。可以參考8.9和9.21小節的內容。
                  <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>

                              哎呀哎呀视频在线观看