python缩进失败?

时间:2011-12-10 12:10:29

标签: python python-3.x

我正在尝试为一个我正在研究的小程序编写一个类,我遇到了一个奇怪的缩进失败。我想知道我写的内容是否真的有问题,或者是否是解析器的错。这在Fedora 15的python 3.2软件包中失败了。

  def __getitem__(self, key):
    if CharacterStats.usesSubStats:
      if key in self.subStats:
        return self.subStats[key]
    elif key in self.stats: #change this to 'if' and it works
      return self.stats[key]
    else:
      raise KeyError(key)
    #otherwise we end up right here.

根据要求,您可以运行它:http://pastebin.com/d8yQUm3U

4 个答案:

答案 0 :(得分:3)

如果我理解正确,你想抛出KeyError if usesSubStats为True,key不在subStats中,或者如果usesSubStats为 假和关键不在统计数据中。所以我认为问题是这样的 如果/ elif / else链接不能像你想象的那样工作。

考虑:

def f(x):
    if x == 1:
        return 'first'
    elif x == 2:
        return 'second'
    else:
        return 'other'

产生

>>> f(1), f(2), f(3), f(4)
('first', 'second', 'other', 'other')

我希望做到的是预期的,是你应该记住的模式。因为在您的测试代码中,useSubStats为True,所以只测试了第一个分支:

def condition(lab, val):
    print('testing condition', lab);
    return val

def g():
    if condition(1, True):
        return 'first branch'
    elif condition(2, False):
        return 'second branch'
    else:
        return 'other branch'
    return 'fallthrough'


>>> g()
testing condition 1
'first branch'

所以你的代码表现得像这样:

def h():
    if condition(1, True):
        if condition('1b', False):
            return 'first branch'
    elif condition(2, False):
        return 'second branch'
    else:
        return 'other branch'
    return 'fallthrough'

>>> h()
testing condition 1
testing condition 1b
'fallthrough'

我不确定你认为它应该如何表现,但似乎你期望在“if.subStats中的if键”测试失败后,执行应该回到if / elif的下一个成员/ else分支一级并测试。但这根本不是它的工作方式。

有几种简单的方法可以获得您想要的行为:一种是将其展平以便它是

    if CharacterStats.usesSubStats and key in self.subStats:

相反,它将评估为False,因此下一个分支进行测试,或者 - 如果您发现自己 - 将elif设为if,这再次导致该条件被独立测试,或在之前的答案中重写。

这有意义吗? if / elif / else列表描述了一系列可能性,其中条件是按顺序测试的,并且只执行对应于第一个真实条件的分支(将最后的else作为'elif 1:')。根据分支中发生的情况,您不会移动到下一个分支。

答案 1 :(得分:2)

当且仅当otherwise we end up right here为真且CharacterStats.usesSubStats为假时,您才可以在标有key in self.subStats的行上结束。

当您将elif更改为if时,您可以消除这种可能性:代码永远无法到达otherwise we end up right here行。

很难说这两个版本中的哪一个是正确的。如果我已经正确地猜到了你的意图,也许下面的内容可能会更清楚地替代它们:

  def __getitem__(self, key):
    if CharacterStats.usesSubStats:
        if key in self.subStats:
            return self.subStats[key]
    elif key in self.stats:
        return self.stats[key]
    raise KeyError(key)

答案 2 :(得分:0)

我认为你应该用#otherwise..缩进raise,因为后者在最终的else内,而且“外部块”永远不会到达。因此,合理的, IMO,IndentationError。

答案 3 :(得分:0)

由于self.statsself.subStats是字典,如果它们不包含KeyError,它们都会提出key

那么为什么不写:

def __getitem__(self, key):
    if CharacterStats.usesSubStats:
        return self.subStats[key]
    return self.stats[key]

或者也许:

def __getitem__(self, key):
    try:
        if CharacterStats.usesSubStats:
            return self.subStats[key]
        return self.stats[key]
    except KeyError:
        raise CharacterStatsError(key)