In python3.x, you can use function annotations:
>>> def foo(indict: dict(apple=None, pear=None)):
... print(indict)
...
>>> foo(dict())
{}
You can even go crazy with the now more widely accepted (by the interpreter) Ellipsis
literal
>>> 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
As you can see from my first example, the annotation it doesn't enforce anything. You'd have to perform the validation in the function itself although I suppose you could introspect the required keys from the annotations1 if you wanted to keep it DRY, but it's probably not worth the effort for just 2 keys...
In python2.x (and more traditionally), perhaps you'd just want to put the information in the docstring ;-) -- And I'd recommend you do that for python3.x as well since that's the traditional place to go looking for documentation ...
1keys = foo.__annotations__['indict'].keys() - {'extra_items'}
UPDATE
Note that now with fancy things like mypy sitting around, this answer is maybe a little outdated. You might consider annotating with a TypedDict
from mypy_extensions
. That should set expectations for your users and maybe even help catch some bugs if you use a type-checker like 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:
...
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…