尝试从类继承时出现“x实例没有属性y”的错误

5

我真的不明白我做错了什么,因为当我在“小规模”尝试时,它是有效的。

我有一个名为Play()的类

代码如下:

class Play():
    def __init__(self):
        file = open("/home/trufa/Desktop/test", "r")
        self.word = random.choice(file.readlines()).rstrip()
        self.errAllowed = 7
        self.errMade = 0
        self.errList = []
        self.cheatsAllowed = 2##chetas not incrementing
        self.cheatsMade =0
        self.wordList = ["*"]*len(self.word) ##this one is the one I want to have available in another class

接下来我有另一个名为Score()的类。

class Score(Play):
    def __init__(self):
        self.initialScore = 0

    def letterGuess(self):
        self.initialScore += 1
        return self.errList

我实例化了两个对象:

game = Play()
points = Score()

如果我这样做:

print points.letterGuess()

它给我报错了:

Traceback (most recent call last):
  File "/home/trufa/workspace/hangpy/src/v2.py", line 188, in <module>
    startGame()
  File "/home/trufa/workspace/hangpy/src/v2.py", line 134, in startGame
    print points.letterGuess()
  File "/home/trufa/workspace/hangpy/src/v2.py", line 79, in letterGuess
    return self.errList
AttributeError: Score instance has no attribute 'errList'

我不明白为什么我可以轻松做到这一点:

class One():
    def __init__(self):
        self.list= [1,2]

class Two(One):
    def meth(self):
        return self.list

uan = One()
tu = Two()

print uan.list 
print tu.meth() ## Both output [1,2]

我对面向对象编程非常陌生,可能会犯各种愚蠢的错误,但我无法找出问题所在!

我认为我已经发布了所有相关的代码,但如果你认为错误可能出现在其他地方,我可以提供它。

正如我所说,我很陌生,所以这可能与继承无关,我只是认为当你从另一个类中获取“某些东西”时,它被称为继承(你现在一定在屏幕前大喊大叫)


你能执行 return Play.errlist 吗? - Matt Habel
@Matt: 他不是, 因为那个类没有那个名称的类变量。 - user395760
打印tu.meth() ## 两者都输出[1,2],不要吸毒。 - 735Tesla
3个回答

12

您重写了原始的__init__,这样它就不会被调用,也不会初始化成员变量。您必须单独调用父类的__init__,通常使用以下代码片段:

def __init__(self):
    super(Score, self).__init__()

详情请参见super()文档。然而,super()仅适用于所谓的新式类。因此,您必须将Play的定义更改为从object继承:

class Play(object)

或者直接调用父类的方法:

def __init__(self):
    Play.__init__(self)

1
进一步澄清,你必须在2.x中从object继承。在3.x中,旧式类被淘汰,因此从object继承是不必要的。 - senderle
@senderle:没错,谢谢。我应该开始尊重3,不再认为2.x是默认选择。 - Boldewyn
@Bolderwyn,我自己也在努力做这件事情 - 因此才有了这个评论。 :) - senderle
@Trufa:不,我也犯了同样的错误,当我第一次开始使用它时。super()的第一个参数是自己的类,在pastie示例中是Two。可以这样想:super() 返回 其第一个参数的超类。 - Boldewyn
1
刚刚通过delicious读到这篇文章:http://rhettinger.wordpress.com/2011/05/26/super-considered-super/ - Boldewyn
显示剩余6条评论

4
当你从类Play继承时,你自动获得在Play定义中创建的属性,但你不会获得在Play.__init__中创建的属性。你必须像这样显式调用它:
class Score(Play):
    def __init__(self):
        Play.__init__(self)
        self.initialScore = 0

请参考Boldewyn的建议,使用super实现此功能;但在我看来,在调整super之前,您应该先熟悉继承的基本工作方式。
进一步解释,如果您不像在这种情况下覆盖__init__,则它会被继承并自动调用。

非常感谢,我相信这很显而易见,但我想你必须在某个时候学习它 :) +1 给第一个并且正确的答案! - Trufa

2

你忘记初始化超类。

class Score(Play):
  def __init__(self):
    super(Score, self).__init__()
    self.initialScore = 0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接