What is the correct (or best) way to subclass the Python set class, adding a new instance variable?

前端 未结 7 1029
囚心锁ツ
囚心锁ツ 2021-01-01 20:45

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

7条回答
  •  谎友^
    谎友^ (楼主)
    2021-01-01 20:58

    Assuming the other answers are correct, and overriding all the methods is the only way to do this, here's my attempt at a moderately elegant way of doing this. If more instance variables are added, only one piece of code needs to change. Unfortunately if a new binary operator is added to the set object, this code will break, but I don't think there's a way to avoid that. Comments welcome!

    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')
    

提交回复
热议问题