Предполагая, что другие ответы верны, и переопределение всех методов - единственный способ сделать это, вот моя попытка в меру элегантного способа сделать это. Если добавлено больше переменных экземпляра, нужно изменить только один фрагмент кода. К сожалению, если новый бинарный оператор будет добавлен к объекту set, этот код сломается, но я не думаю, что есть способ избежать этого. Комментарии приветствуются!
def foocopy(f):
def cf(self, new):
r = f(self, new)
r.foo = self.foo
return r
return cf
class Fooset(set):
def __init__(self, s = []):
set.__init__(self, s)
if isinstance(s, Fooset):
self.foo = s.foo
else:
self.foo = 'default'
def copy(self):
x = set.copy(self)
x.foo = self.foo
return x
@foocopy
def __and__(self, x):
return set.__and__(self, x)
@foocopy
def __or__(self, x):
return set.__or__(self, x)
@foocopy
def __rand__(self, x):
return set.__rand__(self, x)
@foocopy
def __ror__(self, x):
return set.__ror__(self, x)
@foocopy
def __rsub__(self, x):
return set.__rsub__(self, x)
@foocopy
def __rxor__(self, x):
return set.__rxor__(self, x)
@foocopy
def __sub__(self, x):
return set.__sub__(self, x)
@foocopy
def __xor__(self, x):
return set.__xor__(self, x)
@foocopy
def difference(self, x):
return set.difference(self, x)
@foocopy
def intersection(self, x):
return set.intersection(self, x)
@foocopy
def symmetric_difference(self, x):
return set.symmetric_difference(self, x)
@foocopy
def union(self, x):
return set.union(self, x)
f = Fooset([1,2,4])
f.foo = 'bar'
assert( (f | f).foo == 'bar')