不能在子的初始化程序中的列表推导中调用父方法,但显式循环有效

mSS*_*SSM 8 python inheritance python-3.x

child类从继承parent类.child我在构造函数内部 通过重复调用中定义的成员函数初始化一个list-type成员变量.事实证明,如果我通过显式循环并附加返回的每个值进行初始化,一切正常.xsfoo()parentxsfoo()

但是,如果我尝试在列表理解中做同样的事情,我会收到一个奇怪的错误.为什么会出现此错误?在这种情况下,列表理解和显式循环之间有什么区别?

有效的代码的MWE:

class parent(object):
    def __init__(self):
        self.x = 5

    def foo(self, a):
        return self.x


class child(parent):
    def __init__(self):
        super().__init__()

        self.xs = []
        for i in range(9):
            self.xs.append(super().foo(i))    

mychild = child()
Run Code Online (Sandbox Code Playgroud)

child列表理解的定义:

class child(parent):
    def __init__(self):
        super().__init__()
        self.xs = [super().foo(i) for i in range(9)]
Run Code Online (Sandbox Code Playgroud)

有问题的错误:

% python test.py
Traceback (most recent call last):
  File "test.py", line 20, in <module>
    mychild = child()
  File "test.py", line 17, in __init__
    self.xs = [super().foo(i) for i in range(9)]
  File "test.py", line 17, in <listcomp>
    self.xs = [super().foo(i) for i in range(9)]
TypeError: super(type, obj): obj must be an instance or subtype of type
zsh: exit 1     python test.py
Run Code Online (Sandbox Code Playgroud)

jon*_*rpe 7

列表推导实际上是在一个单独的范围内运行的(参见例如,为什么一个类变量没有在列表推导中定义而另一个是?),所以super没有参数的隐式形式在列表推导中不起作用.

您有两个选择,假设您不想返回标准for循环:

  1. 使用显式形式super,传递类和实例参数:super(child, self).foo(i); 要么
  2. 正如您继承foo的那样parent,只需在实例上调用它:self.foo(i).