python缩进失败?

python缩进失败?,python,python-3.x,Python,Python 3.x,我正试图为我一直在开发的一个小程序编写一个类,但我遇到了一个奇怪的缩进失败。我想知道我写的东西是否真的有问题,或者是解析器的错。这在Fedora15的Python3.2包中失败 def __getitem__(self, key): if CharacterStats.usesSubStats: if key in self.subStats: return self.subStats[key] elif key in self.stats: #c

我正试图为我一直在开发的一个小程序编写一个类,但我遇到了一个奇怪的缩进失败。我想知道我写的东西是否真的有问题,或者是解析器的错。这在Fedora15的Python3.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.

根据要求,您可以运行它:

您可以在标记为
的行上结束,否则我们就在这里结束了
当且仅当
CharacterStats.UseSubstats
为true且
键入self.subStats
为false

当您将
elif
更改为
if
时,您消除了这种可能性:代码永远无法到达
,否则我们就在这里结束了

很难说这两个版本中哪一个是正确的。如果我猜对了你的意图,或许以下两种方法都更为清晰:

  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)

我认为你应该将
#缩进,否则..
提升
,因为后者在最后的
else
中,并且永远不会到达“外部块”。。因此,我认为这是一个合理的缩进错误。

如果我理解正确,您希望在 usesSubStats为True,且键不在subStats中,或者如果usesSubStats为 False和key不在统计信息中。所以我认为问题在于 如果/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 key in self.subStats”测试失败后,执行应该返回到if/elif/else分支的下一个成员,并进行一级测试。不过,这根本不是它的工作原理

有几种简单的方法可以让你达到你想要的行为:一种是把它展平,让它变得更简单

    if CharacterStats.usesSubStats and key in self.subStats:
相反,它将计算为False,因此下一个分支将被测试,或者——正如您自己发现的那样——将elif设为if,这再次导致独立测试该条件,或者像前面的答案一样重写


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

因为
self.stats
self.subStats
都是字典,如果它们不包含
键,它们都会引发
键错误

那么,为什么不写:

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)

仅供参考,作者建议使用4个空格的缩进,这样可以使代码更具可读性。它完全按照您的要求执行。这当然不是解析器的错。在实现中,与原始问题一样,返回(或抛出)任何内容的唯一时间是如果键位于self.subStats中,否则将不返回任何内容。如果我去掉else语句,它将为任何不在self.subStats中的键提供一个KeyError。我发现,要使其正常工作,唯一的方法是用if替换elif。@Till:您能将代码简化为我们可以运行的完整小示例,并提供与预期相反的输入吗?这不是一个真正的最小示例。您能把它归结为您的getitem方法和几个测试结果的方法调用示例吗?尝试将其作为(失败的)单元测试来编写。我认为您误解了其中的内容。这不会起作用,因为您的代码片段会假定只要
CharacterStats.usesubstats
为真,键就始终位于
self.subStats
中。但事实并非如此。但是我开始意识到我的课堂布置是多么的愚蠢。是的,我出于某种原因认为如果它进入第一个分支,而其中的
如果
失败,它就会跳回elif;而不是完全跳出来。在午夜的时候编码的结果是一种宿醉的结果。