Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中对集合进行子类化时定义u_repr_u_u_Python_Set_Subclassing - Fatal编程技术网

在Python中对集合进行子类化时定义u_repr_u_u

在Python中对集合进行子类化时定义u_repr_u_u,python,set,subclassing,Python,Set,Subclassing,我试图在Python中对set对象进行子类化,使用类似于下面的代码,但我无法为要使用的\uuu repr\uu制定合理的定义 class Alpha(set): def __init__(self, name, s=()): super(Alpha, self).__init__(s) self.name = name 我想定义\uuuu repr\uuuu,以便获得以下输出: >>> Alpha('Salem', (1,2,3)) A

我试图在Python中对
set
对象进行子类化,使用类似于下面的代码,但我无法为要使用的
\uuu repr\uu
制定合理的定义

class Alpha(set):
    def __init__(self, name, s=()):
        super(Alpha, self).__init__(s)
        self.name = name
我想定义
\uuuu repr\uuuu
,以便获得以下输出:

>>> Alpha('Salem', (1,2,3))
Alpha('Salem', set([1, 2, 3]))
但是,如果我不重写
\uuuu repr\uuuu
,我得到的输出将忽略
名称

>>> Alpha('Salem', (1,2,3))
Alpha([1, 2, 3])
…如果我重写
\uuuu repr\uuuu
,则在不创建新集合实例的情况下,无法直接访问集合中的值:

class Alpha(set):
    …
    def __repr__(self):
        return "%s(%r, %r)" % (self.__class__.__name__, self.name, set(self))
这是可行的,但是为
\uu repr\uuu
创建一个新的set实例,然后将其处理,对我来说似乎既笨拙又低效

有没有更好的方法来定义这种类的
\uuuuu repr\uuuu

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

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)

我找不到比这更好的办法了。不过我想这比扔掉一套要好

(Python 2.x)

或者,如果您不喜欢硬编码的类名(尽管这真的不重要)


我想除了展示一些基准之外,我还有一些东西可以满足你的需求。它们几乎都是等价的,尽管我确信内存使用上存在差异

#!/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))")
结果:

Alpha():0.0287627220154

Alpha2():0.0286467552185


Alpha3():0.028522552969

如果子类尝试调用
\uuuu init\uuu
,那么调用
super
的方式将得到无限递归。
super
显式接受类的原因是它知道在方法解析顺序(MRO)中继续的位置。传递
Alpha
(或者如果这是标签所指示的3.x,只需使用
super()
-它以某种方式做正确的事情)。@delnan:Dang。谢谢你。我当时认为我是在聪明地避免显式指定类。@delnan:出于某种原因,Sven Marnach Brily将这个问题标记为Python 3.x。实际上,我使用的是Python2.6。关于最后一次编辑:我认为您应该避免将集合的副本保存在私有属性中,因为这样您就需要保持它的同步。要做到这一点,您仍然需要在每次需要报告时进行复制。对于这种方法,您可能需要将所有set方法调用转发到私有集,并将其完全用作您的数据。是的,我选择使用
list()
,因为这似乎是最简单的,但显然这一点都不重要。我愿意打赌,内存方面,第一个和第二个的效率较低,因为它们正在实例化和丢弃对象。但这只是一个假设,没有实际检查内存/cpu。第三个示例仅获取一个字符串并对其进行重新格式化。我想这是一个问题,
set()
list()
Alpha3
的两个调用快(基准测试可能会说是)。list()肯定比set()更有效。字符串替换比set()稍微好一点,但为他提供了所需的确切格式。因此,这是一个折腾:我觉得所有这些都不太合适:创建和丢弃实例对于较大的列表来说要昂贵得多,而字符串编辑感觉非常脆弱和“不和谐”。我不会硬编码类名,而是使用
self.\uu class.\uu name.\uuu
(像我一样)@gecco:个人偏好。我看不出不硬编码它有多大意义(除非您将有子类化它的类),特别是在某些地方仍然需要它(超级调用)。无论如何,这很容易改变。但是我已经添加了非硬编码的版本以及根据请求添加的版本。我同意@JohnDoe。当您已经需要为super()调用显式使用类名时,我认为这并不重要。但它确实更具动态性。@JohnDoe:我绝对会让类子类化这个类,所以在这里使用动态名称更有意义。
>>> 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))
... 
>>> Alpha('test', (1, 2))
Alpha('test', set([1, 2]))
#!/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))")