简体   繁体   English

Python:继承内置类型

[英]Python: Inheriting from Built-In Types

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. 有一个类Edge,它有自己的属性和方法。 It should also inherit from a class GraphElement. 它还应该继承自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. (GraphElement是在特定图形的上下文之外没有任何意义的每个对象。)但在最基本的级别,边缘只是包含两个节点的元组。 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". 所以(你,v)将包含“垃圾邮件”和“鸡蛋”。 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 : 所以这是我的Edge类及其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). 我得到一个TypeError:tuple()最多需要1个参数(给定2个)。 What am I doing wrong? 我究竟做错了什么?

Since tuples are immutable, you need to override the __new__ method as well. 由于元组是不可变的,因此您还需要覆盖__new__方法。 See http://www.python.org/download/releases/2.2.3/descrintro/#__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)

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所有参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM