-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathpep-0542.txt
162 lines (110 loc) · 3.66 KB
/
pep-0542.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
PEP: 542
Title: Dot Notation Assignment In Function Header
Version: $Revision$
Last-Modified: $Date$
Author: Markus Meskanen <[email protected]>
Status: Rejected
Type: Standards Track
Content-Type: text/x-rst
Created: 10-Feb-2017
Resolution: https://mail.python.org/pipermail/python-dev/2019-March/156695.html
Abstract
========
Function definitions only allow simple function names to be used,
even though functions are assignable first class objects.
This PEP proposes adding support for assigning a function to
a class or instance attribute directly in the function
definition's header by using the dot notation to separate
the object from the function's name.
Although a similar feature, this PEP does not address general
assignment to anything that supports assignment, such as dict keys
and list indexes.
Rationale
=========
Currently if a function needs to be assigned to a class or instance
attribute, it requires an additional assignment statement to be made::
class MyClass:
...
my_instance = MyClass()
def my_function(self):
...
# Assign to class attribute
MyClass.my_function = my_function
# Or assign to instance attribute
my_instance.my_function = my_function
While this isn't usually an inconvenience, using dot notation to
assign directly in the function's header would greatly simplify this::
class MyClass:
...
my_instance = MyClass()
# Assign to class attribute
def MyClass.my_function(self):
...
# Or assign to instance attribute
def my_instance.my_function(self):
...
There are multiple reasons to use this functionality over
a standard class method, for example when the class is referenced
inside the function's header (such as with decorators and typing).
This is also useful when an instance requires a callback attribute::
class Menu:
def __init__(self, items=None, select_callback=None):
self.items = items if items is not None else []
self.select_callback = select_callback
my_menu = Menu([item1, item2])
def my_menu.select_callback(item_index, menu):
print(menu.items[item_index])
As opposed to::
my_menu = Menu([item1, item2])
def select_callback(item_index, menu):
print(menu.items[item_index])
my_menu.select_callback = select_callback
Or defining them in an "unnatural" order::
def select_callback(item_index, menu):
print(menu.items[item_index])
my_menu = Menu([item1, item2], select_callback)
It reads better than the "unnatural" way, since you already know at
the time of the function definition what it's goig to be used for.
It also saves one line of code while removing visual complexity.
The feature would also avoid leaving the function's name into
the global namespace::
eggs = 'something'
def Spam.eggs(self):
...
def Cheese.eggs(self):
...
assert eggs == 'something'
Ideally this would be just syntastic sugar::
def x.y():
...
# Equals to
def y():
...
x.y = y
Similar to how decorators are syntastic sugar::
@decorate
def f():
...
# Equals to
def f():
...
f = decorate(f)
Implementation
==============
The `__name__` would follow the principles of a normal function::
class MyClass:
def my_function1(self):
...
def MyClass.my_function2(self):
...
assert my_function1.__name__ == 'my_function1'
assert my_function2.__name__ == 'my_function2'
The grammar would use `dotted_name` to support chaining of attributes::
def Person.name.fset(self, value):
self._name = value
Backwards Compatibility
=======================
This PEP is fully backwards compatible.
Copyright
=========
This document has been placed in the public domain.