Skip to content

Commit 5fb29c1

Browse files
committed
Add the args and kwargs page
1 parent 464d959 commit 5fb29c1

File tree

2 files changed

+81
-0
lines changed

2 files changed

+81
-0
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
.. _types_for_args_and_kwargs:
2+
3+
Adding types for ``*args`` and ``**kwargs``
4+
===========================================
5+
6+
Given a function like this:
7+
8+
.. code-block:: python
9+
10+
def foo(*args: X, **kwargs: Y) -> None:
11+
pass
12+
13+
The types of ``args`` and ``kwargs`` will be ``tuple[X, ...]`` and
14+
``dict[str, Y]`` respectively.
15+
16+
Avoid args+kwargs, replicate the parent method's signature
17+
----------------------------------------------------------
18+
19+
When overriding a method defined in a parent class, it's better to be a little
20+
verbose and replicate the parent signature, even if it is unchanged in the child
21+
class and those arguments aren't used.
22+
23+
So instead of:
24+
25+
.. code-block:: python
26+
27+
from typing import Any
28+
29+
class Parent:
30+
def some_method(self, var1: int, *, var2: bool) -> str:
31+
...
32+
33+
class Child(Parent):
34+
def some_method(self, *args: Any, **kwargs: Any) -> str:
35+
super().some_method(*args, **kwargs)
36+
37+
Use:
38+
39+
.. code-block:: python
40+
41+
class Parent:
42+
def some_method(self, var1: int, *, var2: bool) -> str:
43+
...
44+
45+
class Child(Parent):
46+
def some_method(self, var1: int, *, var2: bool) -> str:
47+
super().some_method(var1, var2=var2)
48+
# Do other things
49+
50+
Mypy does not support defining the signature of a method in terms of
51+
the signature of a different method (like the method being overridden) so it's
52+
best to explicitly replicate the signature of the parent method.
53+
54+
Avoid kwargs, replace dictionaries with custom types
55+
----------------------------------------------------
56+
57+
Rather than using ``**kwargs`` to pass dictionaries of options between functions,
58+
consider defining a custom type to pass instead. E.g. a class defined with
59+
``dataclasses``, ``attrs`` or other similar libraries. Types with explicit fields
60+
provide better type safety than dictionaries as mypy can't be certain of what
61+
keys are present in a dictionary.
62+
63+
Use ``typing.Unpack``
64+
---------------------
65+
66+
It's also possible to use ``typing.Unpack`` to explicitly define the
67+
types of the ``kwargs`` dictionary. E.g.
68+
69+
.. code-block:: python
70+
71+
from typing import TypedDict, Unpack
72+
73+
class Args(TypedDict):
74+
name: str
75+
age: int
76+
77+
def foo(**kwargs: Unpack[Args]) -> str:
78+
...
79+
80+
This will indicate to mypy that ``kwargs`` is a dictionary of type ``Args``.

docs/advice/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ Kraken Static Typing Advice
88
advice/understanding_typevars
99
advice/strongly_typed_decorators_and_descriptors
1010
advice/using_abc_vs_protocols
11+
advice/types_for_args_and_kwargs

0 commit comments

Comments
 (0)