1 Invocations in classic Python:
2
3 f(1, 2, 3) # positional
4 f(1, 2) # positional with defaults
5 f(1, 2, c=3) # keywords
6 f(1, c=3) # keywords with defaults
7 f(1, 2, 3, 4) # extra positional arguments
8 f(1, 2, 3, d=4) # extra keyword arguments
9 f(1, 2, *args) # positional bundles (possibly with defaults)
10 f(1, 2, **kw) # keyword bundles (possibly with defaults)
11
12 Note that f is never fixed before run-time in Python.
13
14 Comparison to invocations in C:
15
16 f(1, 2, 3) # positional, f known at compile-time
17 f(1, 2, 3) # positional, f is appropriate function pointer
18 # ie. (*f)(A, B, C)
19
20 Least expensive cases:
21
22 f(1, 2, 3) # put arguments on stack
23 # if f is not known, add arguments vs. parameters check
24 f(1, 2) # to handle defaults, introduce default "filling" where
25 # not enough arguments are given
26 # if f is not known, this is obviously done at run-time
27
28 More expensive cases:
29
30 f(1, 2, c=3) # prepare stack using parameter details
31 # (provided c is a known parameter)
32 # if f is not known, this is obviously done at run-time
33 f(1, c=3) # as with the previous case, with default "filling" done
34 # where not enough arguments are given
35 # if f is not known, this is obviously done at run-time
36 # but with all defaults copied in before keywords are
37 # assigned (since their positions and thus the positions
38 # of missing parameters cannot be known)
39
40 Awkward cases:
41
42 f(1, 2, 3, 4) # extra positional arguments
43 f(1, 2, 3, d=4) # extra keyword arguments
44 f(1, 2, *args) # positional bundles (possibly with defaults)
45 f(1, 2, **kw) # keyword bundles (possibly with defaults)
46
47 These cases require additional structures to be created, potentially at
48 run-time.
49
50 Methods vs. functions:
51
52 f(obj, 1, 2) # f known as function at compile-time:
53 # f(obj, 1, 2)
54 # f known as C.m at compile-time:
55 # m(obj "assert isinstance(obj, C)", 1, 2)
56 # f not known at compile-time:
57 # f(<context>, obj, 1, 2) for instance-accessed methods
58 # f(obj, 1, 2) for class-accessed methods
59 # f(obj, 1, 2) for functions
60
61 (Could either have universal context usage even for functions, which would
62 ignore them, or attempt to remove contexts when functions are called.)
63
64 Argument lists for functions:
65
66 f(obj, 1, 2) # f known as function at compile-time
67
68 f -> don't get any context information
69 obj -> argument #1
70 1 -> argument #2
71 2 -> argument #3
72
73 Argument lists for methods:
74
75 f(obj, 1, 2) # f known as C.m at compile-time (context is C)
76
77 f -> C.m - don't get any context information
78 obj -> argument #1
79 1 -> argument #2
80 2 -> argument #3
81
82 Argument lists for methods:
83
84 f(obj, 1, 2) # f known as C.m at compile-time (context is an instance)
85
86 f -> C.m
87 -> context is argument #1
88 obj -> argument #2
89 1 -> argument #3
90 2 -> argument #4
91
92 Argument lists for unknown callables:
93
94 f(obj, 1, 2) # f not known at compile-time
95
96 f -> f
97 -> load context for argument #1
98 obj -> argument #2
99 1 -> argument #3
100 2 -> argument #4
101
102 Then, check the context and shift the frame if necessary:
103
104 <context> is module or class:
105 (<context>, obj, 1, 2) -> (obj, 1, 2)
106
107 <context> is instance: no change
108
109 Functions as methods:
110
111 def f(x, y, z): ...
112 class C:
113 m = f
114 c = C()
115 ...
116 f(obj, 1, 2) # no restrictions on obj
117 obj.m(1, 2) # f(obj, 1, 2)
118 C.m(obj, 1, 2) # f(obj "assert isinstance(obj, C)", 1, 2)