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 in frame
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 frame 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 classes:
93
94 f(obj, 1, 2) # f known as C at compile-time
95
96 f -> C.__new__ - don't get any context information
97 -> any __init__ method will be called from C.__new__
98 obj -> argument #1
99 1 -> argument #2
100 2 -> argument #3
101
102 Argument lists for unknown callables:
103
104 f(obj, 1, 2) # f not known at compile-time
105
106 f -> f
107 -> load context for argument #1
108 obj -> argument #2
109 1 -> argument #3
110 2 -> argument #4
111
112 Then, check the context and shift the frame if necessary:
113
114 <context> is module or class:
115 (<context>, obj, 1, 2) -> (obj, 1, 2)
116
117 <context> is instance: no change
118
119 Defaults for unknown callables:
120
121 f(obj) # f not known at compile-time
122
123 f -> f
124 -> load context for argument #1
125 obj -> argument #2
126
127 Then, check the number of arguments and the availability of defaults against
128 the details provided by the callable's structure.
129
130 Functions as methods:
131
132 def f(x, y, z): ...
133 class C:
134 m = f
135 c = C()
136 ...
137 f(obj, 1, 2) # no restrictions on obj
138 obj.m(1, 2) # f(obj, 1, 2)
139 C.m(obj, 1, 2) # f(obj "assert isinstance(obj, C)", 1, 2)