【问题标题】:How to use python superclass and inheritance (turtle graphics example)?如何使用python超类和继承(海龟图形示例)?
【发布时间】:2019-06-13 17:44:04
【问题描述】:

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

from turtle import Turtle, _Screen, Screen    

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

wn = Screen()
tortoise = 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()

它的工作原理是这样的,我会得到一个白色的窗户,上面有一只圆乌龟。但如果我取消注释 setupscreensizebgcolor 部分,我会得到一个错误:

AttributeError: 'window' 对象没有属性 '_tracing'

AttributeError: 'window' 对象没有属性 'cv'

所以我必须在 window 类中的 __init__ 之前再次声明一些参数,以使这行得通。似乎我缺少一些东西。为什么乌龟继承了一切并且工作得很好,但是 _Screen 没有使用所有必要的参数进行初始化?

【问题讨论】:

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


    【解决方案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 程序中嵌入 使用。 嵌入式 方法使用RawTurtleTurtleScreen 和可选的Scrolled Canvas。这些类可能更容易子类化,更好的方法可能是通过在 tkinter 中嵌入 turtle 并根据需要进行子类化来构建您自己的独立海龟等价物。

    【讨论】:

    • 谢谢,这似乎有效。您说 TurtleScreen 初始化程序以不友好的方式被调用以供子类使用,您能否对此进行一些扩展? TurtleScreen.__init__(self, _Screen._canvas):是因为 _Screen._canvas 部分吗?应该是 self._canvas 吧?
    • @BogdanPrădatu,对 _Screen 的父级的初始化调用是在旧的 Python 2 样式中完成的,而不是对 super() 的 Python 3 调用。旧式调用包含硬编码到其中的对象层次结构的信息。新样式解决了这个问题。此外,部分问题可能是尝试将 standalone 乌龟子类化,因此我在答案的末尾添加了一个简短的讨论。
    【解决方案2】:

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

    再次感谢,伙计!

    【讨论】:

      猜你喜欢
      • 2014-05-18
      • 2014-03-18
      • 2020-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-19
      相关资源
      最近更新 更多