Permalink
Cannot retrieve contributors at this time
162 lines (110 sloc)
3.66 KB
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| PEP: 542 | |
| Title: Dot Notation Assignment In Function Header | |
| Version: $Revision$ | |
| Last-Modified: $Date$ | |
| Author: Markus Meskanen <markusmeskanen@gmail.com> | |
| 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. |