[Python-ideas] Define a method or function attribute outside of a class with the dot operator

Terry Reedy tjreedy at udel.edu
Fri Feb 10 21:05:49 EST 2017


On 2/10/2017 4:13 AM, Markus Meskanen wrote:
> I'm suggesting the addition of support to using a dot notation when
> defining a function to be a method of a class, or a callback attribute.

My default starting position for every proposed syntax addition is -1.

1. Additions usually make Python more complicated and harder to learn. 
(This can be argued in particular cases.)

2. Syntax changes, when used, cut code off from past versions.

Consequently, to me, there should be a non-trivial gain to compensate 
for the above.

> For example:
>
>     def foo(self):
>         pass
>     Foo.foo = foo
>
> Becomes:
>
>     def Foo.foo(self):
>         pass

Saving about 10 keystrokes is close to trivial.  If Foo is defined in 
the same file, then putting the def in the class statement would save 
even more.  I am not enthusiastic about enablin the following style of 
class definition.

class Foo: "Object that implement the Foo protocol.

def Foo.__init__(self, x):
     self.x = s

def Foo.__getitem__(self, key):
     return vars(Foo)[key]

...

> And when an object needs a callback as an 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(self, item_index):
>         print(self.items[item_index])

A function with a 'self' parameter is normally an instance method (a 
function attribute of the class).  As an instance attribute, it will 
have be called as inst.select_callback(inst, index).  But I suppose you 
could find an example function that I like better as an instance attribute.

> As opposed to:
>
>     my_menu = Menu([item1, item2])
>
>     def select_callback(self, item_index):
>         print(self.items[item_index])
>     my_menu.select_callback = select_callback

or
     my_menu.select_callback = (lambda self, item_index:
         print(self.items[item_index]))

The problem with two-phase initialization is that one temporarily has a 
partially initialized and likely useless object.  I am not enthusiastic 
about encouraging this.

> Or defining them in "unnatural" order:

To me, this is the natural and proper order: create all the objects 
needed to initialize an instance before creating it.  When __init__ 
returns, the instance is ready to go.

In tkinter programming, callbacks must be defined
before they are used in a bind or after call, which passes them on to 
tk, where they are not directly accessible as attributes.

>     def select_callback(self, item_index):
>         print(self.items[item_index])
>
>     my_menu = Menu([item1, item2], select_callback)

Looks good to me ;-)

-- 
Terry Jan Reedy



More information about the Python-ideas mailing list