Не работает декоратор, выдаёт ошибку TypeError: BasicButtons.my_decorator() missing 1 required positional argument: 'func'

В GUI tkinter разрабатываю калькулятор. При нажатии на кнопку С (метод clear_text_field) ранее введенные цифры удаляются и появляется 0. Для оптимизации метода clear_text_field внедрил декоратор "my_decorator", но почему-то выдаёт ошибку:

TypeError: BasicButtons.my_decorator() missing 1 required positional argument: 'func'

Если его закомментировать, а метод раскомментировать всё работает. В чем ошибка?

from tkinter import *
from tkinter.ttk import Frame, Button, Style
import functools

class BasicButtons(Frame):
    def __init__(self, master):
        super().__init__()
        self.memory = "0"
        self.my_window()

    def padding_button(self):  # rr отделяем кнопки друг от друга padding в 5px
        for el in range(5):
            self.columnconfigure(el, pad=5)
        for el1 in range(6):
            self.rowconfigure(el1, pad=5)

    def make_digit_button(self, digit):  # rr создание цифровых кнопок
        return Button(self, text=digit, style='btn_color.TButton', command=lambda: self.add_element(digit))

    def my_window(self):
        Style().configure("TFrame")  # background="blue"
        Style().configure("TButton", padding=(0, 5, 0, 5), font='serif 12', foreground='#F8F8FF', borderwidth=2,
                          relief=GROOVE)
        Style().configure('one.TButton', background='red')
        # yy настройка фона и текста при наведении мыши
        Style().configure('btn_color.TButton', foreground='#007BA7')
        Style().map("btn_color.TButton",
                    foreground=[('pressed', '#4da3c1'), ('active', '#71b5cd')],
                    background=[('pressed', '!disabled', '#e1e1e1'), ('active', '#ececec')])

        self.padding_button()  # yy отделяем кнопки друг от друга padding в 5px

        # yy показываем цифровое поле
        self.text_field = Text(self, foreground='black', padx=10, pady=5, relief='sunken', bd=5,
                               font=('serif', 14, 'bold'),
                               height=1, width=10)
        self.text_field.insert('end', '0', 'right')  # yy центрирование справа
        self.text_field.tag_configure('right', justify='right')
        self.text_field['state'] = 'disable'
        self.text_field.grid(row=0, columnspan=5, sticky='we', padx=10, pady=(5, 10))
        Button(self, text="C", style='one.TButton', command=lambda: self.clear_text_field()).grid(row=1, column=4)

        # yy Оформление кнопок
        self.make_digit_button('7').grid(row=3, column=0)
        self.make_digit_button('8').grid(row=3, column=1)
        self.make_digit_button('9').grid(row=3, column=2)
        self.make_digit_button('4').grid(row=4, column=0)
        self.make_digit_button('5').grid(row=4, column=1)
        self.make_digit_button('6').grid(row=4, column=2)
        self.make_digit_button('1').grid(row=5, column=0)
        self.make_digit_button('2').grid(row=5, column=1)
        self.make_digit_button('3').grid(row=5, column=2)
        self.make_digit_button('0').grid(row=6, columnspan=2, sticky='we', padx=2, pady=(3, 4))
        self.make_digit_button('.').grid(row=6, column=2)


    def my_decorator(self, func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            self.text_field['state'] = 'normal'
            self.text_field.delete(1.0, END)
            func(*args, **kwargs)
            self.text_field.tag_configure('right', justify='right')
            self.text_field['state'] = 'disable'
            return
        return wrapper

    @my_decorator
    def clear_text_field(self):  # rr удаление информации в текстовом поле
        self.text_field.insert(1.0, '0', 'right')

    # def clear_text_field(self):  # rr удаление информации в текстовом поле
    #     self.text_field['state'] = 'normal'
    #     self.text_field.delete(1.0, END)
    #     self.text_field.insert(1.0, '0', 'right')
    #     self.text_field.tag_configure('right', justify='right')
    #     self.text_field['state'] = 'disable'

    def add_element(self, elem):  # rr вывод цифр на дисплей
        self.text_field['state'] = 'normal'
        value = self.text_field.get(1.0, 'end').strip()  # yy удаляем перенос на другую строку
        if (value[0] == '0' and elem == '.') or (value[0] == '0' and len(value) >= 2 and value[1] == '.'):
            self.text_field.delete(1.0, END)  # yy очищаю строку
            self.text_field.insert(1.0, value + elem, 'right')  # yy выравниваю текст справа
        elif value[0] == '0':
            self.text_field.delete(1.0, END)
            self.text_field.insert(1.0, elem, 'right')
        else:
            self.text_field.delete(1.0, END)
            self.text_field.insert(1.0, value + elem, 'right')
        self.text_field.tag_configure('right', justify='right')
        self.text_field['state'] = 'disable'


class Calculator(Tk):
    def __init__(self):
        super().__init__()
        self.frame_a = BasicButtons(self)
        self.frame_a.pack(side=LEFT, padx=10, pady=10)


if __name__ == '__main__':
    app = Calculator()
    app.title("Калькулятор - обычный режим")
    app.mainloop()

Ответы (1 шт):

Автор решения: Amgarak

В декоратор мы передаём сам метод, а уже в обёртке принимаем все его параметры в том числе и объект класса:

def my_decorator(func):
    @functools.wraps(func)
    def wrapper(self, *args, **kwargs):
        self.text_field['state'] = 'normal'
        self.text_field.delete(1.0, END)
        func(self, *args, **kwargs)
        self.text_field.tag_configure('right', justify='right')
        self.text_field['state'] = 'disable'
        return
    return wrapper
→ Ссылка