<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之旅 廣告
                ## 問題 你有一個函數或方法,它使用*args和**kwargs作為參數,這樣使得它比較通用,但有時候你想檢查傳遞進來的參數是不是某個你想要的類型。 ## 解決方案 對任何涉及到操作函數調用簽名的問題,你都應該使用 `inspect` 模塊中的簽名特性。我們最主要關注兩個類:`Signature` 和 `Parameter` 。下面是一個創建函數前面的交互例子: >>> from inspect import Signature, Parameter >>> # Make a signature for a func(x, y=42, *, z=None) >>> parms = [ Parameter('x', Parameter.POSITIONAL_OR_KEYWORD), ... Parameter('y', Parameter.POSITIONAL_OR_KEYWORD, default=42), ... Parameter('z', Parameter.KEYWORD_ONLY, default=None) ] >>> sig = Signature(parms) >>> print(sig) (x, y=42, *, z=None) >>> 一旦你有了一個簽名對象,你就可以使用它的 `bind()` 方法很容易的將它綁定到 `*args` 和 `**kwargs` 上去。下面是一個簡單的演示: >>> def func(*args, **kwargs): ... bound_values = sig.bind(*args, **kwargs) ... for name, value in bound_values.arguments.items(): ... print(name,value) ... >>> # Try various examples >>> func(1, 2, z=3) x 1 y 2 z 3 >>> func(1) x 1 >>> func(1, z=3) x 1 z 3 >>> func(y=2, x=1) x 1 y 2 >>> func(1, 2, 3, 4) Traceback (most recent call last): ... File "/usr/local/lib/python3.3/inspect.py", line 1972, in _bind raise TypeError('too many positional arguments') TypeError: too many positional arguments >>> func(y=2) Traceback (most recent call last): ... File "/usr/local/lib/python3.3/inspect.py", line 1961, in _bind raise TypeError(msg) from None TypeError: 'x' parameter lacking default value >>> func(1, y=2, x=3) Traceback (most recent call last): ... File "/usr/local/lib/python3.3/inspect.py", line 1985, in _bind '{arg!r}'.format(arg=param.name)) TypeError: multiple values for argument 'x' >>> 可以看出來,通過將簽名和傳遞的參數綁定起來,可以強制函數調用遵循特定的規則,比如必填、默認、重復等等。 下面是一個強制函數簽名更具體的例子。在代碼中,我們在基類中先定義了一個非常通用的 `__init__()` 方法,然后我們強制所有的子類必須提供一個特定的參數簽名。 from inspect import Signature, Parameter def make_sig(*names): parms = [Parameter(name, Parameter.POSITIONAL_OR_KEYWORD) for name in names] return Signature(parms) class Structure: __signature__ = make_sig() def __init__(self, *args, **kwargs): bound_values = self.__signature__.bind(*args, **kwargs) for name, value in bound_values.arguments.items(): setattr(self, name, value) # Example use class Stock(Structure): __signature__ = make_sig('name', 'shares', 'price') class Point(Structure): __signature__ = make_sig('x', 'y') 下面是使用這個 `Stock` 類的示例: >>> import inspect >>> print(inspect.signature(Stock)) (name, shares, price) >>> s1 = Stock('ACME', 100, 490.1) >>> s2 = Stock('ACME', 100) Traceback (most recent call last): ... TypeError: 'price' parameter lacking default value >>> s3 = Stock('ACME', 100, 490.1, shares=50) Traceback (most recent call last): ... TypeError: multiple values for argument 'shares' >>> ## 討論 在我們需要構建通用函數庫、編寫裝飾器或實現代理的時候,對于 `*args` 和 `**kwargs` 的使用是很普遍的。但是,這樣的函數有一個缺點就是當你想要實現自己的參數檢驗時,代碼就會笨拙混亂。在8.11小節里面有這樣一個例子。這時候我們可以通過一個簽名對象來簡化它。 在最后的一個方案實例中,我們還可以通過使用自定義元類來創建簽名對象。下面演示怎樣來實現: from inspect import Signature, Parameter def make_sig(*names): parms = [Parameter(name, Parameter.POSITIONAL_OR_KEYWORD) for name in names] return Signature(parms) class StructureMeta(type): def __new__(cls, clsname, bases, clsdict): clsdict['__signature__'] = make_sig(*clsdict.get('_fields',[])) return super().__new__(cls, clsname, bases, clsdict) class Structure(metaclass=StructureMeta): _fields = [] def __init__(self, *args, **kwargs): bound_values = self.__signature__.bind(*args, **kwargs) for name, value in bound_values.arguments.items(): setattr(self, name, value) # Example class Stock(Structure): _fields = ['name', 'shares', 'price'] class Point(Structure): _fields = ['x', 'y'] 當我們自定義簽名的時候,將簽名存儲在特定的屬性 `__signature__` 中通常是很有用的。這樣的話,在使用 `inspect` 模塊執行內省的代碼就能發現簽名并將它作為調用約定。 >>> import inspect >>> print(inspect.signature(Stock)) (name, shares, price) >>> print(inspect.signature(Point)) (x, y) >>>
                  <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>

                              哎呀哎呀视频在线观看