Class and tkinter problem

Terry Reedy tjreedy at udel.edu
Thu Jan 7 15:35:47 EST 2021


On 1/7/2021 4:20 AM, Terry Reedy wrote:
> On 1/7/2021 2:42 AM, Christian Gollwitzer wrote:
>> Am 07.01.21 um 08:29 schrieb Paulo da Silva:
>>
>>> Does anybody know why cmd method isn't called when I change the button
>>> state (clicking on it) in this example?
>>> I know that this seems a weird class use. But why doesn't it work?
>>> Thanks.
>>>
>>> class C:
>>>      from tkinter import Checkbutton
>>>      import tkinter
>>>
>>>      @staticmethod
>> ^^it works if you remove the staticmethod here
> 
> staticmethods are essentially useless in Python.  What little was gained 
> by their addition is partly offset by the introduced confusion.

>>>      def cmd():
>>>          print("Test")

The confusion is that methods are callable, whereas 'staticmethods' are 
not.  I was not completely aware of this until pointed out by Peter 
Otten with example

"    cmd()

Traceback (most recent call last):
   File "<pyshell#28>", line 1, in <module>
     class C:
   File "<pyshell#28>", line 4, in C
     cmd()
TypeError: 'staticmethod' object is not callable

You have to go through the descriptor protocol:"

Indeed, dir(cmd) shows that it does not have a .__call__ attribute.

>      top=tkinter.Tk()
>      cb=Checkbutton(command=cmd)

> Button commands have to be tcl functions.  Tkinter wraps Python 
> functions as tcl function.  Static methods also wrap python functions, 
> as a .__func__ attribute.  So the code if one passes cmd.__func__.

"So the code works if one passes the callable cmd.__func__."

>> Maybe there is a bug in tkinter, that it doesn't work with static 
>> methods?
> 
> One could propose that tkinter test whether callables are staticmethods 

Command options, as documented, must be callables. Neither staticmethods 
nor classmethods are callable.

> and unwrap them when they are.

  I would propose instead that if possible tkinter raise TypeError when 
passed a non-callable as a command.

> Classmethods also do not work as is.  By experiment, the following works.
>      cb=Checkbutton(command=lambda: C.cmd.__func__(C))
> But if the class were nested, it would be more complicated.


-- 
Terry Jan Reedy




More information about the Python-list mailing list