Поскольку объекты экземпляров классов в языке Python могут вызываться как функции, если они наследуют метод __call__ для перехвата этой операции, их также можно использовать в качестве обработчиков событий. В примере 7.15 демонстрируется класс, реализующий необходимый интерфейс.
Пример 7.15. PP4E\Gui\Intro\gui3d.py
import sys
from tkinter import *
class HelloCallable:
def __init__(self): # __init__ вызывается при создании объекта self.msg = ‘Hello __call__ world’
def __call__(self):
print(self.msg) # __call__ вызывается при попытке обратиться sys.exit() # к объекту класса как к функции
widget = Button(None, text=’Hello event world’, command=HelloCallable()) widget.pack() widget.mainloop()
Здесь экземпляр класса HelloCallable, зарегистрированный в command, тоже может вызываться как обычная функция — Python вызовет его метод __call__ для обработки операции вызова, выполняемой в tkinter при нажатии кнопки. В данном случае обобщенный метод __call__ фактически замещает связанный метод. Обратите внимание, что здесь для хранения информации, используемой при обработке событий, задействуется атрибут self.msg — self, являющийся ссылкой на исходный экземпляр класса, который автоматически передается при вызове специального метода __call__.
Все четыре версии gui3 создают одинаковые окна (рис. 7.11), но при нажатии на кнопку выводят в stdout различные сообщения:
C:\…\PP4E\Gui\Intro> python gui3.py
Hello, I must be going…
C:\…\PP4E\Gui\Intro> python gui3b.py Hello lambda world
C:\…\PP4E\Gui\Intro> python gui3c.py
C:\…\PP4E\Gui\Intro> python gui3d.py
Hello __call__ world
Существуют свои основания для использования каждого из приемов определения обработчиков событий (функция, lambda-выражение, метод класса, вызываемый класс), но необходимо перейти к более крупным примерам, чтобы выйти из области чистого теоретизирования.
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011