伪造python中的元组类

时间:2017-04-07 19:13:48

标签: python python-3.x inheritance types

我需要一个新类型,比如说MyTuple,这样我就可以创建这样的对象:obj = MyTuple((1,2,3)),例如:

  1. obj的行为与本机元组完全相同(也在性能方面)
  2. isinstance(obj, tuple)返回False
  3. 这背后的原因是我需要在Pandas中使用元组作为索引,但是当Pandas检测到索引的值是元组时,它使用多索引代替,这是我不想要的。

    因此,以下内容不起作用:

    class MyTuple(tuple):
        pass
    

    这满足了我的第一个要求,但不满足第二个要求,所以如果我使用MyTuple个对象作为索引,Pandas仍会从它们创建多索引。

    另一种解决方案是使用组合而不是继承,实现Sequence abc并将真元组作为对象属性,为它提供包装方法:

    from collections.abc import Sequence
    class MyTuple(Sequence):
        def __init__(self, initlist=None):
            self.data = ()   # A true tuple is stored in the object
            if initlist is not None:
                if type(initlist) == type(self.data): self.data = initlist
                elif isinstance(initlist, MyTuple): self.data = initlist.data
                else:  self.data = tuple(initlist)
        def __getitem__(self, i): return self.data[i]
        def __len__(self): return len(self.data)
        def __hash__(self): return hash(self.data)
        def __repr__(self): return repr(self.data)
        def __eq__(self, other): return self.data == other
        def __iter__(self): yield from self.data.__iter__()
    

    此类型满足第二个要求(isinstance(obj, tuple)返回False),并提供与真实tuple相同的接口(您可以通过索引访问元素,您可以将其与另一个元组,你可以用它作为字典键等)。在语法和语义上这个解决方案对我有好处。

    然而,就性能而言,它不是真正的tuple。在我的应用程序中,我必须在这些对象(以及具有真tuple s的这些对象)之间进行大量的比较,因此方法MyTuple.__eq__()被称为很多次。这引入了性能损失。使用MyTuple而不是真元组,我的程序将运行时间乘以6。

    然后,我需要的是像我的第一次尝试(一个继承自tuple的类),但后来可以"谎言"关于成为一个元组,如果通过isinstance()询问(因为这是Pandas如果发现它是一个元组,因此应该创建一个多索引)。

    我读过Python的datamodel__instancecheck__()方法,但我认为它们在这里没用,因为我应该在tuple中实现这些方法,而不是{ {1}},但这是不可能的。

    也许有一些使用元类的技巧会做到这一点,但我并不完全理解这个概念,看它与这个问题的关系。

    我可以以某种方式实现我的目标吗?

2 个答案:

答案 0 :(得分:1)

tuple

类似的其他方法。

仍然不是真正的{{1}}表现,但我能想到的最接近......可能。

答案 1 :(得分:0)

您在性能方面遇到的主要问题是,Python的基础资料是在高度优化的C(或其他语言 - 有十几个好的实现,还有更多的实现)中实现的。

当您在Python中实现某些内容时,请记住它的解释或部分编译最多。如果必须在运行时重新解释每一行,即使给出了良好的中间代码,也无法获得最佳性能。