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

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ## 問題 你在寫一段代碼,最終需要創建一個新的類對象。你考慮將類的定義源代碼以字符串的形式發布出去。并且使用函數比如 `exec()` 來執行它,但是你想尋找一個更加優雅的解決方案。 ## 解決方案 你可以使用函數 `types.new_class()` 來初始化新的類對象。你需要做的只是提供類的名字、父類元組、關鍵字參數,以及一個用成員變量填充類字典的回調函數。例如: # stock.py # Example of making a class manually from parts # Methods def __init__(self, name, shares, price): self.name = name self.shares = shares self.price = price def cost(self): return self.shares * self.price cls_dict = { '__init__' : __init__, 'cost' : cost, } # Make a class import types Stock = types.new_class('Stock', (), {}, lambda ns: ns.update(cls_dict)) Stock.__module__ = __name__ 這種方式會構建一個普通的類對象,并且安裝你的期望工作: >>> s = Stock('ACME', 50, 91.1) >>> s <stock.Stock object at 0x1006a9b10> >>> s.cost() 4555.0 >>> 這種方法中,一個比較難理解的地方是在調用完 `types.new_class()` 對 `Stock.__module__` 的賦值。每次當一個類被定義后,它的 `__module__` 屬性包含定義它的模塊名。這個名字用于生成 `__repr__()` 方法的輸出。它同樣也被用于很多庫,比如 `pickle` 。因此,為了讓你創建的類是“正確”的,你需要確保這個屬性也設置正確了。 如果你想創建的類需要一個不同的元類,可以通過 `types.new_class()` 第三個參數傳遞給它。例如: >>> import abc >>> Stock = types.new_class('Stock', (), {'metaclass': abc.ABCMeta}, ... lambda ns: ns.update(cls_dict)) ... >>> Stock.__module__ = __name__ >>> Stock <class '__main__.Stock'> >>> type(Stock) <class 'abc.ABCMeta'> >>> 第三個參數還可以包含其他的關鍵字參數。比如,一個類的定義如下: class Spam(Base, debug=True, typecheck=False): pass 那么可以將其翻譯成如下的 `new_class()` 調用形式: Spam = types.new_class('Spam', (Base,), {'debug': True, 'typecheck': False}, lambda ns: ns.update(cls_dict)) `new_class()` 第四個參數最神秘,它是一個用來接受類命名空間的映射對象的函數。通常這是一個普通的字典,但是它實際上是 `__prepare__()` 方法返回的任意對象,這個在9.14小節已經介紹過了。這個函數需要使用上面演示的 `update()` 方法給命名空間增加內容。 ## 討論 很多時候如果能構造新的類對象是很有用的。有個很熟悉的例子是調用 `collections.namedtuple()` 函數,例如: >>> Stock = collections.namedtuple('Stock', ['name', 'shares', 'price']) >>> Stock <class '__main__.Stock'> >>> `namedtuple()` 使用 `exec()` 而不是上面介紹的技術。但是,下面通過一個簡單的變化,我們直接創建一個類: import operator import types import sys def named_tuple(classname, fieldnames): # Populate a dictionary of field property accessors cls_dict = { name: property(operator.itemgetter(n)) for n, name in enumerate(fieldnames) } # Make a __new__ function and add to the class dict def __new__(cls, *args): if len(args) != len(fieldnames): raise TypeError('Expected {} arguments'.format(len(fieldnames))) return tuple.__new__(cls, args) cls_dict['__new__'] = __new__ # Make the class cls = types.new_class(classname, (tuple,), {}, lambda ns: ns.update(cls_dict)) # Set the module to that of the caller cls.__module__ = sys._getframe(1).f_globals['__name__'] return cls 這段代碼的最后部分使用了一個所謂的”框架魔法”,通過調用 `sys._getframe()` 來獲取調用者的模塊名。另外一個框架魔法例子在2.15小節中有介紹過。 下面的例子演示了前面的代碼是如何工作的: >>> Point = named_tuple('Point', ['x', 'y']) >>> Point <class '__main__.Point'> >>> p = Point(4, 5) >>> len(p) 2 >>> p.x 4 >>> p.y 5 >>> p.x = 2 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: can't set attribute >>> print('%s %s' % p) 4 5 >>> 這項技術一個很重要的方面是它對于元類的正確使用。你可能像通過直接實例化一個元類來直接創建一個類: Stock = type('Stock', (), cls_dict) 這種方法的問題在于它忽略了一些關鍵步驟,比如對于元類中 `__prepare__()` 方法的調用。通過使用 `types.new_class()` ,你可以保證所有的必要初始化步驟都能得到執行。比如,`types.new_class()` 第四個參數的回調函數接受 `__prepare__()` 方法返回的映射對象。 如果你僅僅只是想執行準備步驟,可以使用 `types.prepare_class()` 。例如: import types metaclass, kwargs, ns = types.prepare_class('Stock', (), {'metaclass': type}) 它會查找合適的元類并調用它的 `__prepare__()` 方法。然后這個元類保存它的關鍵字參數,準備命名空間后被返回。 更多信息, 請參考 [PEP 3115](https://www.python.org/dev/peps/pep-3115/) ,以及 [Python documentation](https://docs.python.org/3/reference/datamodel.html#metaclasses) .
                  <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>

                              哎呀哎呀视频在线观看