I have a question concerning subtypes of built-in types and their constructors. I want a class to inherit both from tuple and from a custom class.
Let me give you the concrete example. I work a lot with graphs, meaning nodes connected with edges. I am starting to do some work on my own graph framework.
There is a class Edge, which has its own attributes and methods. It should also inherit from a class GraphElement. (A GraphElement is every object that has no meaning outside the context of a specific graph.) But at the most basic level, an edge is just a tuple containing two nodes. It would be nice syntactic sugar if you could do the following:
edge = graph.create_edge("Spam","Eggs")
(u, v) = edge
So (u,v) would contain "Spam" and "Eggs". It would also support iteration like
for node in edge: ...
I hope you see why I would want to subtype tuple (or other basic types like set).
So here is my Edge class and its init :
class Edge(GraphElement, tuple):
def __init__(self, graph, (source, target)):
GraphElement.__init__(self, graph)
tuple.__init__((source, target))
When i call
Edge(aGraph, (source, target))
I get a TypeError: tuple() takes at most 1 argument (2 given). What am I doing wrong?
Since tuples are immutable, you need to override the __new__ method as well. See 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)
For what you need, I would avoid multiple inheritance and would implement an iterator using generator:
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
In this case both usages work just fine:
e = Edge(None, ("Spam","Eggs"))
(s, t) = e
print s, t
for p in e:
print p
你需要覆盖__new__
- 当前tuple.__new__
被调用(因为你没有覆盖它)与你传递给Edge
所有参数。
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.