Python:从内置类型继承

3 投票
3 回答
2729 浏览
提问于 2025-04-15 11:50

我有一个关于内置类型的子类型和它们的构造函数的问题。我想要一个类同时继承元组和一个自定义类。

让我给你一个具体的例子。我经常处理图形,也就是节点和连接这些节点的边。我开始着手自己做一个图形框架。

有一个类叫做边(Edge),它有自己的属性和方法。它还应该继承一个叫做图形元素(GraphElement)的类。(图形元素是指在特定图形的上下文中才有意义的对象。)但从最基本的角度来看,一条边其实就是一个包含两个节点的元组。如果能这样写就太好了:

edge = graph.create_edge("Spam","Eggs")
(u, v) = edge

这样 (u,v) 就会包含“Spam”和“Eggs”。它也应该支持像这样进行迭代:

for node in edge: ...

我希望你能理解我为什么想要让边类成为元组的子类(或者其他基本类型,比如集合)。

所以这是我的边类和它的 init 方法:

class Edge(GraphElement, tuple):

def __init__(self, graph, (source, target)):
    GraphElement.__init__(self, graph)
    tuple.__init__((source, target))

当我调用

Edge(aGraph, (source, target))

时,我得到了一个类型错误:tuple() 最多接受 1 个参数(给了 2 个)。我哪里出错了?

3 个回答

3

你需要重写一下 __new__ 这个方法——现在调用的是 tuple.__new__,因为你没有重写它,所以所有你传给 Edge 的参数都被传给了这个方法。

6

对于你的需求,我建议避免使用多重继承,而是用生成器来实现一个迭代器:

class GraphElement:
    def __init__(self, graph):
        pass

class Edge(GraphElement):
    def __init__(self, graph, (source, target)):
        GraphElement.__init__(self, graph)
        self.source = source
        self.target = target

    def __iter__(self):
        yield self.source
        yield self.target

在这种情况下,这两种用法都能正常工作:

e = Edge(None, ("Spam","Eggs"))
(s, t) = e
print s, t
for p in e:
    print p
10

因为元组是不可改变的,所以你需要重写 __new__ 方法。具体可以参考这个链接:http://www.python.org/download/releases/2.2.3/descrintro/#__new__

class GraphElement:
    def __init__(self, graph):
        pass

class Edge(GraphElement, tuple):
    def __new__(cls, graph, (source, target)):
        return tuple.__new__(cls, (source, target))
    def __init__(self, graph, (source, target)):
        GraphElement.__init__(self, graph)

撰写回答