簡體   English   中英

是否可以將字典解構為鍵入的關鍵字 arguments?

[英]Is it possible to deconstruct a dictionary into typed keyword arguments?

假設我有一本字典:

from typing import Dict
T: Dict[str, int] = {
    'a': 2,
    'b': 3,
}

現在我想定義一個 function 關鍵字 arguments 取自上面的字典:

def func(**T):
  print (locals())

目標是正確完成 function 的類型檢查:

func(2)    # should work
func('2')  # should work
func(a=2)  # should work
func([2])  # should report a type issue
func(c=2)  # should give TypeError

我試過了,但我無法讓它工作。 這可能嗎?

這不完全是你要找的東西,但你可以試試typeguard庫,我想你可以做類似的事情

from typing import Dict

from typeguard import check_type


def something(**kwargs):
    check_type("kwargs", kwargs, Dict[str, int])


if __name__ == "__main__":
    something(**{"A": 1})
    something(**{"A": "1"})

但我認為您無法使用**kwargs語法對實際的 function 調用進行類型檢查,因為參數名稱直到運行時才定義,因此在運行時之前無法為每個關鍵字參數分配類型。 如果你提前知道允許的值類型,你可以做類似的事情

from typing import Dict

from typeguard import typeguard, check_type


@typeguard
def something(a: int, b: int):
    check_type("kwargs", kwargs, Dict[str, int])


if __name__ == "__main__":
    something(**{"A": 1})
    something(**{"A": "1"})

或者你可以做

from typing import Dict

from typeguard import typeguard


@typeguard
def something(kwargs: Dict[str, int]):
    # then do something with **kwargs
    _inner(**kwargs)

def _inner(**kwargs):
    pass


if __name__ == "__main__":
    something(**{"A": 1})
    something(**{"A": "1"})

最近有一項關於允許使用TypedDict來注釋PEP 692中的**kwargs的機制的提案。 然而,討論仍在進行中 AFAIK 並且有一些有效的 arguments 反對這一點。

其中一個論點是缺乏對此類功能的強烈動機。 換句話說,你為什么真的需要這個? 以你的情況為例。 如果你已經在某處定義了一個類型化字典,並且你知道 function 必須采用這樣一個字典作為它的參數,為什么不以這樣一個字典的形式定義一個常規的 function 參數:

from typing import TypedDict


class SpecialDict(TypedDict, total=False):
    a: int
    b: int


def func(d: SpecialDict) -> None:
    print(d)


if __name__ == "__main__":
    func({"a": 1})
    func({"b": 1})
    func({"c": 1})

導致mypy使用以下內容抱怨最后一行:

error: Extra key "c" for TypedDict "SpecialDict"

無論如何,在 function 關鍵字參數中,關鍵字參數都被視為字典,因此與普通字典相比,我真的看不到用它們構建 function 的好處。 特別是因為**kwargs表示您似乎並不真正想要的靈活性。


除此之外,您的要求還有許多問題。 如果你像這樣定義一個 function def f(**kwargs): ...它只需要關鍵字 arguments 而沒有位置 arguments。這意味着這些都不起作用,無論你如何注釋 function:

func(2)
func('2')
func([2])

此外,您希望某些類型注釋導致TypeError ,這永遠不會自行發生,因為類型注釋主要是為了 static 類型檢查器的利益。 Python 解釋器根本不關心它們。

如果您確實希望它關心,則必須自己在運行時實現檢查類型的邏輯。


我建議堅持 Python 的禪宗並且明確。 如果您真的希望您的 function 只接受特定關鍵字 arguments,請相應地定義它:

def func(*, a: int, b: int) -> None:
    ...

如果需要,您仍然可以通過使用正確的鍵解壓字典來調用它:

d = {"a": 1, "b": 2}
func(**d)

希望這可以幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM