在Python中子类化set时定义__repr__

me_*_*and 6 python set subclassing

我正在尝试set使用类似于下面的代码在Python中对该对象进行子类化,但是我无法找到一个合理的定义__repr__来使用.

class Alpha(set):
    def __init__(self, name, s=()):
        super(Alpha, self).__init__(s)
        self.name = name
Run Code Online (Sandbox Code Playgroud)

我想以__repr__这样的方式定义,我可以获得以下输出:

>>> Alpha('Salem', (1,2,3))
Alpha('Salem', set([1, 2, 3]))
Run Code Online (Sandbox Code Playgroud)

但是,如果我不覆盖__repr__,我得到的输出忽略了name值...

>>> Alpha('Salem', (1,2,3))
Alpha([1, 2, 3])
Run Code Online (Sandbox Code Playgroud)

...如果我覆盖__repr__,我无法直接访问集合中的值而无需创建新的集合实例:

class Alpha(set):
    …
    def __repr__(self):
        return "%s(%r, %r)" % (self.__class__.__name__, self.name, set(self))
Run Code Online (Sandbox Code Playgroud)

这是有效的,但为此创建一个新的集合实例__repr__将被处理似乎笨重和低效我.

有没有更好的方法来定义__repr__这种类?

编辑:我遇到的另一个解决方案:我可以在本地存储集合.它似乎比其他选项稍微整洁(为每次调用__repr__或使用某种形式的字符串操作创建和销毁某些东西),但对我来说似乎仍然不太理想.

class Alpha(set):
    def __init__(self, name, s=()):
        super(Alpha, self).__init__(s)
        self.name = name
        self._set = set(s)
    def __repr__(self):
        return "%s(%r, %r)" % (self.__class__.__name__, self.name, self._set)
Run Code Online (Sandbox Code Playgroud)

jdi*_*jdi 9

除了展示一些基准外,我想我能找到你想要的东西.虽然我确信内存使用量存在差异,但它们几乎都是等效的.

#!/usr/bin/env python

import time

class Alpha(set):
    def __init__(self, name, s=()):
            super(Alpha, self).__init__(s)
            self.name = name
    def __repr__(self):
            return '%s(%r, set(%r))' % (self.__class__.__name__, 
                                        self.name, 
                                        list(self))

class Alpha2(set):
    def __init__(self, name, s=()):
            super(Alpha2, self).__init__(s)
            self.name = name
    def __repr__(self):
            return '%s(%r, set(%r))' % (self.__class__.__name__, 
                                        self.name, 
                                        set(self))

class Alpha3(set):
    def __init__(self, name, s=()):
            super(Alpha3, self).__init__(s)
            self.name = name
    def __repr__(self):
            rep = super(Alpha3, self).__repr__()
            rep = rep.replace(self.__class__.__name__, 'set', 1)
            return '%s(%r, %s)' % (self.__class__.__name__, 
                                    self.name, 
                                    rep)

def timeit(exp, repeat=10000):
    results = []
    for _ in xrange(repeat):
        start = time.time()
        exec(exp)
        end = time.time()-start
        results.append(end*1000)
    return sum(results) / len(results)

if __name__ == "__main__":
    print "Alpha():  ", timeit("a = Alpha('test', (1,2,3,4,5))")
    print "Alpha2(): ", timeit("a = Alpha2('test', (1,2,3,4,5))")
    print "Alpha3(): ", timeit("a = Alpha3('test', (1,2,3,4,5))")
Run Code Online (Sandbox Code Playgroud)

结果:

Alpha():0.0287627220154

Alpha2():0.0286467552185

Alpha3():0.0285225152969