如何使用乌龟超类

时间:2014-04-05 22:52:59

标签: python class inheritance superclass turtle-graphics

我正在使用龟图制作太阳系复制品。 我想创造一个明星和一个行星,它们都继承了同一个海龟超类" solar_element",但我有问题。

我可以使用两种不同的海龟类来制作星球和星球:

from turtle import Turtle

class star(Turtle):
   def __init__(self, Name, Radius, Mass, Colour):
    Turtle.__init__(self, shape = "circle")
    self.Name = Name
    self.Radius = Radius
    self.Mass = Mass
    self.color(Colour)
    self.shapesize(self.Radius/50)

class planet(Turtle):
 def __init__(self, Name, Radius, Mass, Colour, Dist, velX, velY):
    Turtle.__init__(self, shape= "circle")
    self.Name = Name
    self.Radius = Radius
    self.Mass = Mass
    self.color(Colour)
    self.Dist = Dist
    self.velX = velX
    self.velY = velY
    self.x_pos = sun.Radius + self.Dist + self.Radius
    self.y_pos = 0
    self.shapesize(self.Radius/50)

sun = star('myStar', 500.0, 15000.0, "yellow");
earth = planet('P1', 150.0, 1000.0, "green", 0.25, 0.5, 2.0);

但是当我尝试让它们从一个超类继承时,就像这样:

from turtle import Turtle

class solar_element(Turtle):
 def __init__(self, Name, Radius, Mass, Colour):
    self.Name = Name
    self.Radius = Radius
    self.Mass = Mass
    self.Colour = Colour
    self.color(self.Colour)
    self.shapesize(self.Radius/50)

class star(solar_element):
 def __init__(self, Name, Radius, Mass, Colour):
    solar_element.__init__(self, Name, Radius, Mass, Colour)
    Turtle.__init__(self, shape = "circle")

class planet(solar_element):
 def __init__(self, Name, Radius, Mass, Colour, Dist, velX, velY):
    solar_element.__init__(self, Name, Radius, Mass, Colour)
    Turtle.__init__(self, shape = "circle")
    self.Dist = Dist
    self.velX = velX
    self.velY = velY
    self.x_pos = sun.Radius + self.Dist + self.Radius
    self.y_pos = 0

sun = star('myStar', 500.0, 15000.0, "yellow");
earth = planet('P1', 150.0, 1000.0, "green", 0.25, 0.5, 2.0);

我收到以下错误:

Traceback (most recent call last):
  File "C:\Users\Kev\Dropbox\OOP\testing_classes.py", line 62, in <module>
    sun = star('myStar', 500.0, 15000.0, "yellow");
  File "C:\Users\Kev\Dropbox\OOP\testing_classes.py", line 47, in __init__
    solar_element.__init__(self, Name, Radius, Mass, Colour)
  File "C:\Users\Kev\Dropbox\OOP\testing_classes.py", line 42, in __init__
    self.color(self.Colour)
  File "C:\Python33\lib\turtle.py", line 2208, in color
    pcolor = self._colorstr(pcolor)
  File "C:\Python33\lib\turtle.py", line 2688, in _colorstr
    return self.screen._colorstr(args)
AttributeError: 'star' object has no attribute 'screen'

我意识到我可以坚持使用两个类,但我想使用一个超类,因为我还在尝试学习python。

3 个答案:

答案 0 :(得分:1)

首先在Turtlesolar_element类中调用star构造函数之前调用planet构造函数。

因此,请将__init__类的star方法中的代码更改为:

Turtle.__init__(self, shape = "circle")
solar_element.__init__(self, Name, Radius, Mass, Colour)

__init__类的planet方法中的代码更改为:

Turtle.__init__(self, shape = "circle")
solar_element.__init__(self, Name, Radius, Mass, Colour)

首先,当我们想要覆盖它时,我们通常需要在__init__方法中调用基类的构造函数。 实际上,当我们想要在__init__方法中使用类的一部分时,我们首先调用它,例如color方法, 在任何人都可以使用之前,该方法需要进行一些准备。 这里举例说明screen color方法的Turtle需要在我们使用此方法之前设置。

使用您的代码进行一些重构:

  • 类名通常应使用CapWords惯例
  • 您不需要在行尾添加;
  • 变量名称应为小写,并根据需要用下划线分隔,以提高可读性。
  • 使用super(YourInheritedClass, self).__init__()代替 ParentClass.__init__(self)

代码:

from turtle import Turtle

class SolarElement(Turtle):
    def __init__(self, name, radius, mass, colour, shape='circle'):
        # or Turtle.__init__(self, shape=shape)
        super(SolarElement, self).__init__(shape=shape)
        self.name = name
        self.radius = radius
        self.mass = mass
        self.colour = colour
        self.color(self.colour)
        self.shapesize(self.radius / 50)


class Star(SolarElement):
    def __init__(self, name, radius, mass, colour,
                 shape='circle'):
        SolarElement.__init__(self, name, radius, mass, colour,
                              shape=shape)


class Planet(SolarElement):
    def __init__(self, name, radius, mass, colour, dist, vel_x, vel_y,
                 shape='circle'):
        SolarElement.__init__(self, name, radius, mass, colour,
                              shape=shape)
        self.dist = dist
        self.vel_x = vel_x
        self.vel_y = vel_y
        self.x_pos = sun.radius + self.dist + self.radius
        self.y_pos = 0

sun = Star('myStar', 500.0, 15000.0, "yellow")
earth = Planet('P1', 150.0, 1000.0, "green", 0.25, 0.5, 2.0)

答案 1 :(得分:1)

您遇到的问题是,如果self.color(self.Colour)班级solar_object.__init__Turtle中的来电__init__无法正常运作方法尚未被调用。

您的当前代码在调用Turtle.__init__之后调用solar_object.__init__ ,因此修复的第一个问题就是首先调用它。

但是,我建议更改一些内容,并solar_object.__init__拨打Turtle.__init__。这样,您不需要每个后来的子类也以正确的顺序获取初始化器。

class solar_element(Turtle):
    def __init__(self, Name, Radius, Mass, Colour):
        Turtle.__init__(self, shape="circle")
        # ...

我进一步建议您了解super函数,Python提供了一种在超类中调用方法的方法,而不是专门命名它们。而不是Turtle.__init__,而不是super().__init__

答案 2 :(得分:0)

由于您要派生Turtle的子类,因此需要在子类__init__()方法中初始化基类:

from turtle import Turtle

class solar_element(Turtle):
    def __init__(self, Name, Radius, Mass, Colour):
        super(solar_element, self).__init__()
        self.Name = Name
        self.Radius = Radius
        self.Mass = Mass
        self.Colour = Colour
        self.color(self.Colour)
        self.shapesize(self.Radius/50)

class star(solar_element):
    def __init__(self, Name, Radius, Mass, Colour):
        solar_element.__init__(self, Name, Radius, Mass, Colour)
        Turtle.__init__(self, shape = "circle")

class planet(solar_element):
    def __init__(self, Name, Radius, Mass, Colour, Dist, velX, velY):
        super(solar_element, self).__init__()
        solar_element.__init__(self, Name, Radius, Mass, Colour)
        Turtle.__init__(self, shape = "circle")
        self.Dist = Dist
        self.velX = velX
        self.velY = velY
        self.x_pos = sun.Radius + self.Dist + self.Radius
        self.y_pos = 0

sun = star('myStar', 500.0, 15000.0, "yellow")
earth = planet('P1', 150.0, 1000.0, "green", 0.25, 0.5, 2.0)