Как использовать Python суперкласс и наследование (пример графики черепахи)? - PullRequest
0 голосов
/ 19 января 2019

Я играл с графикой черепахи, пытаясь лучше понять объекты, и столкнулся с небольшой проблемой. Я узнал о функции super () и хотел ее использовать:

from turtle import Turtle, _Screen, Screen    

class turtle(Turtle):
    def __init__(self):
        super().__init__(shape="circle")            

wn = Screen()
tortoise = turtle()

Так что, если я сделаю это, все будет работать как шарм. Я получаю экран и могу использовать любой метод Черепахи на своем классе черепах.

from turtle import Turtle, _Screen, Screen

class window(_Screen):
    def __init__(self):
        super().__init__()
        self.setup(500,500)
        self.screensize(1000,1000)
        self.title("Title")
        self.bgcolor("black")

wn = window()

Это также будет прекрасно работать, я получаю то, что спрашиваю: черное окно 1000x1000 в коробке 500x500 с ползунками Нет проблем. Но если я хочу объединить это:

from turtle import Turtle, _Screen, Screen

class window(_Screen):
    def __init__(self):
        super().__init__()
        self.setup(500,500)
        self.screensize(1000,1000)
        self.title("Title")
        self.bgcolor("black")

class turtle(Turtle):
    def __init__(self):
        super().__init__(shape="circle")

wn = window()
tortoise = turtle()

Появится экран, но я получу ошибку от черепахи:

AttributeError: у объекта '_Screen' нет атрибута '_mode'

Я просматривал модуль черепахи и обнаружил, что функция Screen () делает это:

def Screen():
    """Return the singleton screen object.
    If none exists at the moment, create a new one and return it,
    else return the existing one."""
    if Turtle._screen is None:
        Turtle._screen = _Screen()
    return Turtle._screen

Поэтому я изменил класс окна, добавив в него следующее:

from turtle import Turtle, _Screen, Screen

class window(_Screen):
    def __init__(self):
        Turtle._screen = Screen()
        super().__init__()
        #self.setup(500,500)
        #self.screensize(1000,1000)
        #self.title("Title")
        #self.bgcolor("black")

class turtle(Turtle):
    def __init__(self):
        super().__init__(shape="circle")

wn = window()
tortoise = turtle()

Это работает так, я получу белое окно с круглой черепахой. Но если я раскомментирую настройку , размер экрана или bgcolor , Я получу ошибку:

AttributeError: у объекта 'window' нет атрибута '_tracing'

или

AttributeError: объект 'window' не имеет атрибута 'cv'

Так что мне бы снова пришлось объявить некоторые параметры перед __ init __ в окне класса, чтобы он работал. Кажется, что-то мне не хватает. Почему черепаха наследует все и прекрасно работает, но _Screen не инициализируется со всеми необходимыми параметрами?

Ответы [ 2 ]

0 голосов
/ 20 января 2019

После ответа cdlane я обнаружил, что могу сделать это немного проще. Часть Screen() может быть введена в функцию __init__:

from turtle import Turtle, TurtleScreen, _Screen

class window(_Screen):
    def __init__(self):
        super().__init__()
        TurtleScreen.__init__(self, window._canvas)
        if Turtle._screen is None:
            Turtle._screen = self
        self.setup(500,500)
        self.screensize(1000,1000)
        self.title("Title")
        self.bgcolor("black")

class turtle(Turtle):
    def __init__(self):
        super().__init__(shape="circle")
        self.color("white")
        self.speed(0)
        self.circle(50)

wn = window()
tortoise = turtle()

Еще раз спасибо, приятель!

0 голосов
/ 20 января 2019

Как вы обнаружили, черепаха Screen - это лук многих слоев. Есть две проблемы, которые нам нужно решить: класс _Screen вызывает его инициализатор super (TurtleScreen's) таким образом, который не подходит для подкласса; функция Screen() вызывается из множества мест и жестко определяет, какой класс создает экран. Итак, давайте рассмотрим обе проблемы:

import turtle

class MyScreen(turtle._Screen):
    def __init__(self):
        super().__init__()
        turtle.TurtleScreen.__init__(self, MyScreen._canvas)

        self.setup(500, 500)
        self.screensize(1000, 1000)
        self.title("Title")
        self.bgcolor("black")

def MyScreenFunction():
    if turtle.Turtle._screen is None:
        turtle.Turtle._screen = MyScreen()
    return turtle.Turtle._screen

turtle.Screen = MyScreenFunction

class MyTurtle(turtle.Turtle):
    def __init__(self):
        super().__init__(shape="circle")

wn = turtle.Screen()

tortoise = MyTurtle()
tortoise.color('white')

tortoise.circle(100)

wn.mainloop()

Однако, может быть, есть лучший путь. Черепаха может использоваться как автономно , как указано выше, так и , встроенная в программу tkinter. Подход внедренный использует RawTurtle, TurtleScreen и, необязательно, Scrolled Canvas. Эти классы проще разделить на подклассы, и лучшим подходом может быть создание собственного эквивалента автономной черепахи путем внедрения черепахи в tkinter и создания подклассов по мере необходимости.

...