添加新的实例变量的子集化Python设置类的正确(或最佳)方法是什么? [英] What is the correct (or best) way to subclass the Python set class, adding a new instance variable?
问题描述
我实现的对象几乎与集合相同,但是需要一个额外的实例变量,因此我将内置集合对象作为子类.确保在复制我的一个对象时复制此变量的值的最佳方法是什么?
I'm implementing an object that is almost identical to a set, but requires an extra instance variable, so I am subclassing the built-in set object. What is the best way to make sure that the value of this variable is copied when one of my objects is copied?
使用旧的sets模块,以下代码可以完美运行:
Using the old sets module, the following code worked perfectly:
import sets
class Fooset(sets.Set):
def __init__(self, s = []):
sets.Set.__init__(self, s)
if isinstance(s, Fooset):
self.foo = s.foo
else:
self.foo = 'default'
f = Fooset([1,2,4])
f.foo = 'bar'
assert( (f | f).foo == 'bar')
,但是使用内置的set模块不起作用.
but this does not work using the built-in set module.
我能看到的唯一解决方案是重写返回复制的设置对象的每个方法...在这种情况下,我最好也不必费心子类化设置对象.当然有标准的方法可以做到这一点吗?
The only solution that I can see is to override every single method that returns a copied set object... in which case I might as well not bother subclassing the set object. Surely there is a standard way to do this?
(为澄清起见,以下代码不起作用(断言失败):
(To clarify, the following code does not work (the assertion fails):
class Fooset(set):
def __init__(self, s = []):
set.__init__(self, s)
if isinstance(s, Fooset):
self.foo = s.foo
else:
self.foo = 'default'
f = Fooset([1,2,4])
f.foo = 'bar'
assert( (f | f).foo == 'bar')
)
推荐答案
我最喜欢的包装内置集合方法的方法:
My favorite way to wrap methods of a built-in collection:
class Fooset(set):
def __init__(self, s=(), foo=None):
super(Fooset,self).__init__(s)
if foo is None and hasattr(s, 'foo'):
foo = s.foo
self.foo = foo
@classmethod
def _wrap_methods(cls, names):
def wrap_method_closure(name):
def inner(self, *args):
result = getattr(super(cls, self), name)(*args)
if isinstance(result, set) and not hasattr(result, 'foo'):
result = cls(result, foo=self.foo)
return result
inner.fn_name = name
setattr(cls, name, inner)
for name in names:
wrap_method_closure(name)
Fooset._wrap_methods(['__ror__', 'difference_update', '__isub__',
'symmetric_difference', '__rsub__', '__and__', '__rand__', 'intersection',
'difference', '__iand__', 'union', '__ixor__',
'symmetric_difference_update', '__or__', 'copy', '__rxor__',
'intersection_update', '__xor__', '__ior__', '__sub__',
])
与您在自己的答案中所做的基本上相同,但是位置更少.如果您也想对列表和字典做同样的事情,那么放入元类也很容易.
Essentially the same thing you're doing in your own answer, but with fewer loc. It's also easy to put in a metaclass if you want to do the same thing with lists and dicts as well.
这篇关于添加新的实例变量的子集化Python设置类的正确(或最佳)方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!