带有一些强制键的字典作为函数输入

Jan*_*Jan 2 python dictionary

我有一个函数,它有一个字典作为参数.我将传递各种词典,其中包含的条目多于函数内部使用的几个.另外,我想在函数定义中看到需要哪些键.所以我写

def fun(indict=dict(apple=None, pear=None)):
Run Code Online (Sandbox Code Playgroud)

但是,该函数现在接受任何输入为indict.是否有一种聪明的写作方式

any dictionary that has at least the keys 'apple' and 'pear' is accepted.
Run Code Online (Sandbox Code Playgroud)

就像是

def fun(indict=dict(apple=NeedsToBeSpecified, pear=NeedsToBeSpecified)):
Run Code Online (Sandbox Code Playgroud)

mgi*_*son 5

在python3.x中,您可以使用函数注释:

>>> def foo(indict: dict(apple=None, pear=None)):
...     print(indict)
... 
>>> foo(dict())
{}
Run Code Online (Sandbox Code Playgroud)

你甚至可以用现在更广泛接受的(由翻译)Ellipsis文字来疯狂

>>> def foo(indict: dict(apple=None, pear=None, extra_items=...)) -> int:
...     if any(x not in indict for x in ('apple', 'pear')):
...         raise ValueError('message here...')
...     print(indict)
...     return 3
... 
>>> foo({})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in foo
ValueError: message here...
>>> foo({'apple':6, 'pear':4})
{'pear': 4, 'apple': 6}
3
>>> foo({'apple':6, 'pear':4, 'carrot':30000})
{'carrot': 30000, 'pear': 4, 'apple': 6}
3
Run Code Online (Sandbox Code Playgroud)

从我的第一个例子中可以看出,注释它没有强制执行任何操作.你必须在函数本身中执行验证,虽然我想你可以从注释1中反省所需的键,如果你想保持它干,但它可能不值得为2个键的努力......

在python2.x(以及更传统的)中,也许你只想将信息放在docstring中;-) - 我建议你也为python3.x做这个,因为那是传统的去寻找的地方用于文件......

1keys = foo.__annotations__['indict'].keys() - {'extra_items'}

更新 请注意,现在有像mypy这样的花哨的东西,这个答案可能有点过时了.您可以考虑使用TypedDictfrom进行注释mypy_extensions.这应该为您的用户设定期望,如果您使用类型检查器,甚至可能帮助捕获一些错误mypy.

from mypy_extensions import TypedDict

class Apple:
    """Represent an Apple."""

class Pear:
    """Represent a Pear."""

# "annotation-type" for a dictionary that has an apple and pear key whose values are Apple and Pear instances.
FruitBowl = TypedDict("FruitBowl": {"apple": Apple, "Pear": Pear})

def foo(indict: FruitBowl) -> int:
    ...
Run Code Online (Sandbox Code Playgroud)