python 3 : super() raises TypeError unexpectedly

标签 python inheritance typeerror superclass super

来自 Java,我在理解继承、抽象类、静态方法和 Python 中 OO 编程的类似概念时遇到了一些困难。

我有一个表达式树类的实现,给定(简化)

# Generic node class
class Node(ABC):
    @abstractmethod
    def to_expr(self):
        pass

    @staticmethod
    def bracket_complex(child):
        s = child.to_expr()
        return s if isinstance(child, Leaf) or isinstance(child, UnaryOpNode) else "(" + s + ")"


# Leaf class - used for values and variables
class Leaf(Node):
    def __init__(self, val):
        self.val = val

    def to_expr(self):
        return str(self.val)


# Unary operator node
class UnaryOpNode(Node):
    def __init__(self, op, child):
        self.op = op
        self.child = child

    def to_expr(self):
        return str(self.op) + super().bracket_complex(self.child)


# Binary operator node
class BinaryOpNode(Node):
    def __init__(self, op, lchild, rchild):
        self.op = op
        self.lchild = lchild
        self.rchild = rchild

    def to_expr(self):
        return super().bracket_complex(self.lchild) + " " + str(self.op) + " " + super().bracket_complex(self.rchild)


# Variadic operator node (arbitrary number of arguments)
# Assumes commutative operator
class VariadicOpNode(Node):
    def __init__(self, op, list_):
        self.op = op
        self.children = list_

    def to_expr(self):
        return (" " + str(self.op) + " ").join(super().bracket_complex(child) for child in self.children)

to_expr() 方法在 LeafUnaryOpNodeBinaryOpNode 实例上调用时工作正常,但是在 VariadicOpNode 实例上调用时引发 TypeError:

TypeError: super(type, obj): obj must be an instance or subtype of type

super() 突然不起作用的特定类中我做错了什么?

在 Java 中,静态方法会被继承,所以我什至不需要 super 调用,但在 Python 中,情况似乎并非如此。

最佳答案

您在生成器表达式中使用不带参数的 super()super() 很神奇——它依赖于调用者框架中的信息。由于生成器表达式创建了一个附加函数,因此没有参数的 super() 在那里不起作用。然而,由于您的父类(super class)不太可能在方法执行过程中发生变化,您可以将它移出生成器表达式——这也应该加快速度:

def to_expr(self):
    bracket_complex = super().bracket_complex
    return (" " + str(self.op) + " ").join(bracket_complex(child) for child in self.children)

然而,由于静态方法在 Python 中是“继承”的,因此您可以通过 self 调用 super 方法,前提是您没有在子类中覆盖它。因此在这个简单的例子中你可以这样写:

def to_expr(self):
    return (" " + str(self.op) + " ").join(self.bracket_complex(child) for child in self.children)

实现细节是,如果没有提供任何参数,第一个参数应该是调用方框架的 __class__ 单元格中的值,第二个应该是给调用方的第一个参数功能。通常,当在错误的地方使用 super 时,您只会得到一个 SystemError,但是生成器表达式被包装在一个隐式生成器函数中,该函数会创建另一个调用框架。不幸的是,这个函数有一个参数,导致 super() 提示这个异常。

所以通常 super() 将作为第一个参数传递给 Foo,但是在生成器表达式中,传递了一个生成器对象 - 因此很明显 TypeError 需要被引发。

关于 python 3 : super() raises TypeError unexpectedly,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35829643/

相关文章:

javascript - 另一个函数作用域多个 .js 文件问题

python - 无法使用 api 将数据上传到 thingworx

c++ - C++ 中未使用的友元类

c++ - 当类层次结构中只有一个类时,避免在每次函数调用时读取 V 表的开销

c# - 为接口(interface)强制执行某种类类型?

python - 如何修复 TypeError : can only concatenate str (not "list") to str

python - 顺序 Keras 模型能否获得未展平的多维输入(例如图像)(即输入形状是每个图像的 MxN 像素)?

python - 如何使用 SQLalchemy 在 mysql 中创建带有空间列的表?

python - 在 WRDS CRSP 查询中使用来自外部文件的 Python 字典值

python - Adaptive Threshold 参数混淆