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-February-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 attribtue 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.
