如何使用python超类和继承(乌龟图形示例)?

时间:2019-01-19 20:47:10

标签: python python-3.x turtle-graphics super superclass

我一直在研究乌龟图形,试图更好地理解对象,但遇到了一个小问题。我已经了解了super()函数,并想使用它:

from turtle import Turtle, _Screen, Screen    

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

wn = Screen()
tortoise = turtle()

所以,如果我这样做,一切都会像魅力一样。我得到一个屏幕,并且可以在我的turtle类上使用任何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()

这也将很好用,我能得到我想要的:500x500带有滑杆的盒子中的1000x1000黑色窗口。没问题。但是,如果我想将这些结合起来:

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'

我一直在浏览turtle模块,发现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:“窗口”对象没有属性“ _tracing”

  

AttributeError:“窗口”对象没有属性“ cv”

因此,我将不得不再次在 window 类的 __ init __ 之前声明一些参数,以使这行得通。看来我缺少了一些东西。为什么乌龟会继承所有东西并发挥出色作用,但是 _Screen 并未使用所有必需的参数进行初始化?

2 个答案:

答案 0 :(得分:1)

您已经发现,乌龟Screen是多层洋葱。我们需要解决两个问题:_Screen类以对子类不友好的方式调用其上级(TurtleScreen的)初始化程序。 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()

但是,可能还有更好的方法。 Turtle既可以在上面的独立中使用,也可以在tkinter程序中嵌入中使用。 embedded 方法使用RawTurtleTurtleScreen和可选的Scrolled Canvas。这些类可能更易于子类化,更好的方法可能是通过将龟嵌入tkinter并根据需要进行子类化来构建自己的独立龟。

答案 1 :(得分:0)

在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()

再次感谢,队友!