|
5 | 5 |
|
6 | 6 | https://docs.python.org/3/library/functools.html#functools.singledispatch |
7 | 7 |
|
8 | | -For now this is just a simplistic test. If we want to get serious, we must |
9 | | -add support for things like `*args`, `**kwargs`, `typing.Sequence[int]`, |
10 | | -and in 3.8, `typing.Literal['a', 'b', 'c', 'd']`. |
11 | | -
|
12 | 8 | **WARNING: EXPERIMENTAL FEATURE** |
13 | 9 |
|
14 | 10 | This experimental feature is a proof-of-concept provided for technical preview |
@@ -43,41 +39,48 @@ def generic(f): |
43 | 39 | are registered with the decorator `@f.register`, where `f` is the function |
44 | 40 | you decorated with `@generic`. |
45 | 41 |
|
46 | | - Each method must specify type hints **on all of its parameters**. Then, at |
47 | | - call time, the types of **all** arguments, as well as the number of arguments, |
48 | | - are automatically used for choosing which method to call. In other words, multiple |
49 | | - parameters are used for dispatching. |
| 42 | + Each method must specify type hints **on all of its parameters** except |
| 43 | + `**kwargs` (if it has one). Then, at call time, the types of **all** arguments |
| 44 | + (except any bound to `**kwargs`) as well as the number of arguments, are |
| 45 | + automatically used for choosing which method to call. In other words, |
| 46 | + multiple parameters are used for dispatching. |
| 47 | +
|
| 48 | + **Varargs are supported**. To have the contents of `*args` participate in |
| 49 | + dispatching, annotate the parameter as `*args: typing.Tuple[...]`. For the |
| 50 | + `...` part, see the documentation of the `typing` module. Both homogeneous |
| 51 | + and heterogeneous tuples are supported. |
50 | 52 |
|
51 | | - The first match wins, in most-recently-registered order - that is, later |
52 | | - definitions override earlier ones. So specify the implementation with the |
53 | | - most generic types first, and then move on to the more specific ones. The |
54 | | - mnemonic is, "the function is generally defined like this, except if the |
55 | | - arguments match these particular types..." |
| 53 | + The first method that matches wins, in most-recently-registered order. That |
| 54 | + is, later definitions override earlier ones. So specify the implementation |
| 55 | + with the most generic types first, and then move on to the more specific |
| 56 | + ones. The mnemonic is, "the function is generally defined like this, except |
| 57 | + if the arguments match these particular types..." |
56 | 58 |
|
57 | 59 | The point of this feature is to eliminate `if`/`elif`/`elif`... blocks |
58 | 60 | that switch by `isinstance` on arguments, and then raise `TypeError` |
59 | 61 | in the final `else`, by implementing the machinery once centrally. |
60 | 62 |
|
61 | | - Another use case are functions like the builtin `range` where the role |
62 | | - of an argument in a particular position depends on the number of arguments |
63 | | - given to the call. |
| 63 | + Another use case of `@generic` are functions like the builtin `range`, where |
| 64 | + the *role* of an argument in a particular position depends on the *number of* |
| 65 | + arguments passed in the call. |
64 | 66 |
|
65 | 67 | **Differences to tools in the standard library**: |
66 | 68 |
|
67 | | - Unlike `functools.singledispatch`, the `@generic` function itself is |
68 | | - unused. |
| 69 | + Unlike `functools.singledispatch`, the `@generic` function itself is unused. |
69 | 70 |
|
70 | | - Unlike `typing.overload`, the implementations are to be provided in the |
71 | | - method bodies. |
| 71 | + Unlike `typing.overload`, the implementations are given in the method bodies. |
72 | 72 |
|
73 | 73 | **CAUTION**: |
74 | 74 |
|
75 | 75 | To declare a parameter of a method as dynamically typed, explicitly |
76 | 76 | annotate it as `typing.Any`; don't just omit the type annotation. |
77 | | - Explicit is better than implicit; this is a feature. |
| 77 | + Explicit is better than implicit; **this is a feature**. |
| 78 | +
|
| 79 | + Dispatching by the contents of the `**kwargs` dictionary is not (yet) |
| 80 | + supported. |
78 | 81 |
|
79 | | - Currently, advanced features of `typing` such as `Sequence[...]` are |
80 | | - not supported. This may or may not change in the future. |
| 82 | + See the limitations in `unpythonic.typecheck` for which features of the |
| 83 | + `typing` module are supported and which are not. |
81 | 84 | """ |
82 | 85 | # Dispatcher - this will replace the original f. |
83 | 86 | @wraps(f) |
|
0 commit comments