如何使用python超类和继承(乌龟图形示例)?
How to use python superclass and inheritance (turtle graphics example)?
我一直在玩海龟图形,试图更好地理解对象,但遇到了一个小问题。我了解了 super() 函数并想使用它:
from turtle import Turtle, _Screen, Screen
class turtle(Turtle):
def __init__(self):
super().__init__(shape="circle")
wn = Screen()
tortoise = turtle()
所以如果我这样做,一切都会像魅力一样。我得到一个屏幕,我可以在我的乌龟上使用任何乌龟方法 class。
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 的黑色 window 在带滑杆的 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' object has no attribute '_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
所以我修改了 window class 以包含以下内容:
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()
它是这样工作的,我会得到一只白色的window,还有一只圆龟。但是,如果我取消注释 setup,screensize 或bgcolor 部分,我会得到一个错误:
AttributeError: 'window' object has no attribute '_tracing'
或
AttributeError: 'window' object has no attribute 'cv'
所以我又得在__init__之前声明一些参数在window class,让它工作。看来我缺少什么。为什么乌龟继承了一切并且工作得很好,但是 _Screen 没有用所有必要的参数初始化?
如您所见,乌龟 Screen
是多层洋葱。有两个问题我们需要解决:_Screen
class 以一种对 subclass 不友好的方式调用它的超级(TurtleScreen 的)初始化器; Screen()
函数从很多地方调用,它硬编码 class 创建屏幕。因此,让我们解决这两个问题:
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 可以像上面那样 standalone 使用,也可以 embedded 在 tkinter 程序中使用。 嵌入式方法使用RawTurtle
、TurtleScreen
和可选的Scrolled Canvas
。这些 classes 可能更容易 subclass 并且更好的方法可能是通过在 tkinter 中嵌入 turtle 并根据需要 subclassing 来构建您自己的独立 turtle 的等价物。
经过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()
再次感谢,伙计!
我一直在玩海龟图形,试图更好地理解对象,但遇到了一个小问题。我了解了 super() 函数并想使用它:
from turtle import Turtle, _Screen, Screen
class turtle(Turtle):
def __init__(self):
super().__init__(shape="circle")
wn = Screen()
tortoise = turtle()
所以如果我这样做,一切都会像魅力一样。我得到一个屏幕,我可以在我的乌龟上使用任何乌龟方法 class。
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 的黑色 window 在带滑杆的 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' object has no attribute '_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
所以我修改了 window class 以包含以下内容:
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()
它是这样工作的,我会得到一只白色的window,还有一只圆龟。但是,如果我取消注释 setup,screensize 或bgcolor 部分,我会得到一个错误:
AttributeError: 'window' object has no attribute '_tracing'
或
AttributeError: 'window' object has no attribute 'cv'
所以我又得在__init__之前声明一些参数在window class,让它工作。看来我缺少什么。为什么乌龟继承了一切并且工作得很好,但是 _Screen 没有用所有必要的参数初始化?
如您所见,乌龟 Screen
是多层洋葱。有两个问题我们需要解决:_Screen
class 以一种对 subclass 不友好的方式调用它的超级(TurtleScreen 的)初始化器; Screen()
函数从很多地方调用,它硬编码 class 创建屏幕。因此,让我们解决这两个问题:
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 可以像上面那样 standalone 使用,也可以 embedded 在 tkinter 程序中使用。 嵌入式方法使用RawTurtle
、TurtleScreen
和可选的Scrolled Canvas
。这些 classes 可能更容易 subclass 并且更好的方法可能是通过在 tkinter 中嵌入 turtle 并根据需要 subclassing 来构建您自己的独立 turtle 的等价物。
经过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()
再次感谢,伙计!