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

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ## 問題 你想將一個只讀屬性定義成一個property,并且只在訪問的時候才會計算結果。但是一旦被訪問后,你希望結果值被緩存起來,不用每次都去計算。 ## 解決方案 定義一個延遲屬性的一種高效方法是通過使用一個描述器類,如下所示: class lazyproperty: def __init__(self, func): self.func = func def __get__(self, instance, cls): if instance is None: return self else: value = self.func(instance) setattr(instance, self.func.__name__, value) return value 你需要像下面這樣在一個類中使用它: import math class Circle: def __init__(self, radius): self.radius = radius @lazyproperty def area(self): print('Computing area') return math.pi * self.radius ** 2 @lazyproperty def perimeter(self): print('Computing perimeter') return 2 * math.pi * self.radius 下面在一個交互環境中演示它的使用: >>> c = Circle(4.0) >>> c.radius 4.0 >>> c.area Computing area 50.26548245743669 >>> c.area 50.26548245743669 >>> c.perimeter Computing perimeter 25.132741228718345 >>> c.perimeter 25.132741228718345 >>> 仔細觀察你會發現消息 `Computing area` 和 `Computing perimeter` 僅僅出現一次。 ## 討論 很多時候,構造一個延遲計算屬性的主要目的是為了提升性能。例如,你可以避免計算這些屬性值,除非你真的需要它們。這里演示的方案就是用來實現這樣的效果的,只不過它是通過以非常高效的方式使用描述器的一個精妙特性來達到這種效果的。 正如在其他小節(如8.9小節)所講的那樣,當一個描述器被放入一個類的定義時,每次訪問屬性時它的 `__get__()` 、`__set__()` 和 `__delete__()` 方法就會被觸發。不過,如果一個描述器僅僅只定義了一個 `__get__()` 方法的話,它比通常的具有更弱的綁定。特別地,只有當被訪問屬性不在實例底層的字典中時 `__get__()` 方法才會被觸發。 `lazyproperty` 類利用這一點,使用 `__get__()` 方法在實例中存儲計算出來的值,這個實例使用相同的名字作為它的property。這樣一來,結果值被存儲在實例字典中并且以后就不需要再去計算這個property了。你可以嘗試更深入的例子來觀察結果: >>> c = Circle(4.0) >>> # Get instance variables >>> vars(c) {'radius': 4.0} >>> # Compute area and observe variables afterward >>> c.area Computing area 50.26548245743669 >>> vars(c) {'area': 50.26548245743669, 'radius': 4.0} >>> # Notice access doesn't invoke property anymore >>> c.area 50.26548245743669 >>> # Delete the variable and see property trigger again >>> del c.area >>> vars(c) {'radius': 4.0} >>> c.area Computing area 50.26548245743669 >>> 這種方案有一個小缺陷就是計算出的值被創建后是可以被修改的。例如: >>> c.area Computing area 50.26548245743669 >>> c.area = 25 >>> c.area 25 >>> 如果你擔心這個問題,那么可以使用一種稍微沒那么高效的實現,就像下面這樣: def lazyproperty(func): name = '_lazy_' + func.__name__ @property def lazy(self): if hasattr(self, name): return getattr(self, name) else: value = func(self) setattr(self, name, value) return value return lazy 如果你使用這個版本,就會發現現在修改操作已經不被允許了: >>> c = Circle(4.0) >>> c.area Computing area 50.26548245743669 >>> c.area 50.26548245743669 >>> c.area = 25 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: can't set attribute >>> 然而,這種方案有一個缺點就是所有get操作都必須被定向到屬性的 `getter` 函數上去。這個跟之前簡單的在實例字典中查找值的方案相比效率要低一點。如果想獲取更多關于property和可管理屬性的信息,可以參考8.6小節。而描述器的相關內容可以在8.9小節找到。
                  <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>

                              哎呀哎呀视频在线观看