Python:从内置类型继承
我有一个关于内置类型的子类型和它们的构造函数的问题。我想要一个类同时继承元组和一个自定义类。
让我给你一个具体的例子。我经常处理图形,也就是节点和连接这些节点的边。我开始着手自己做一个图形框架。
有一个类叫做边(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)