Исключение при попытке наследовать метод geometry в tkinter

Рейтинг: 1Ответов: 1Опубликовано: 19.06.2023

Я пишу небольшую обертку для tkinter. Я изменяю методы __setitem__, __getitem__, __init__, wm_geometry. Эта обертка имеет цель упростить настройку окна и сделать ее более интуитивной. Одна из ниш для упрощения - wm_geometry, ведь формат ее единственного аргумента может показаться неочевидным. Имеется следующий код, внимание попрошу заострить на методе wm_geometry:

from tkinter import *
from typing import Any


def __str(i: str | None):
    if i == None:
        return ''
    return str(i)

def __unary_str(i: str | None):
    if i == None:
        return ''
    if i >= 0:
        return f'+{i}'
    return str(i)


class Tk(Tk):
    def __init__(
            self, screenName: str | None = None, baseName: str | None = None,
            className: str = "Tk", useTk: bool = True, sync: bool = False,
            use: str | None = None
            ) -> None:
        super().__init__(screenName, baseName, className, useTk, sync, use)
        self._icon_path = 'default'

    def __setitem__(self, key: str, value: Any) -> None:
        match key:
            case 'icon':
                self.iconbitmap(value)
                self._icon_path = value
            case 'title':
                self.title(value)
            case _:
                return super().__setitem__(key, value)
    
    def __getitem__(self, key: str) -> Any:
        match key:
            case 'icon':
                return self._icon_path
            case 'title':
                return self.title()
            case _:
                return super().__getitem__(key)
    
    def wm_geometry(self, *args):
        """Sets geometry of the window. Arguments can be provided in different
        ways:
        wm_geometry(size: tuple, pos: tuple) -> None
        wm_geometry(width: int, height: int, x: int, y: int) -> None
        wm_geometry(geometry: str) -> None
        wm_geometry() -> str
        """
        if not args:
            return super().wm_geometry()
        if len(args) == 4:
            args = ((args[0], args[1]), (args[2], args[3]))
        if len(args) == 2:
            if args[0]:
                size = 'x'.join(map(__str, args[0]))
            else:
                size = ''
            if args[1]:
                pos = ''.join(map(__unary_str, args[1]))
            else:
                pos = ''
            args = [pos+size]
        super().wm_geometry(args[0])
    
    geometry = wm_geometry
    

if __name__ == '__main__':
    root = Tk()
    root.geometry((800, 600), ())

В результате его выполнения получаю исключение:

Traceback (most recent call last):
  File "c:\Users\PCyur\OneDrive\Рабочий стол\tkinter_wrapper.py", line 65, in <module>
    root.geometry((800, 600), ())
  File "c:\Users\PCyur\OneDrive\Рабочий стол\tkinter_wrapper.py", line 50, in wm_geometry
    size = 'x'.join(map(__str, args[0]))
                        ^^^^^
NameError: name '_Tk__str' is not defined

Такого имени в принципе в моем коде на существует, в чем проблема?

Ответы

▲ 1Принят

Переименуйте функции __str и __unary_str в _str и _unary_str соответственно.

Суть ошибки в том, что все имена вида __<ИМЯ> (но без двух подчеркиваний в конце), встречающиеся в теле класса, Python переделывает в _<ИМЯ КЛАССА>__<ИМЯ>.