Cooperative class tree filtering

Alberto Berti alberto at metapensiero.it
Thu Oct 12 19:56:37 EDT 2017


Sorry, i've made a mistake in  the second C body, it's written like: 
>>>>> "me" == Alberto Berti <alberto at metapensiero.it> writes:

    me> I've tried some variants of the 'super()' trick, that sometimes seems to
    me> change behavior if it's written like that or like super(type(self),
    me> self) in no clear (to me, and I failed to find extensive doc on
    me> super()'s behavior) way, with things that stop working if mixins are
    me> involved (even if the mixins do not reimplement the methods involved
    me> here). Eventually i ended implementing a decorator:

    me>   from functools import partial, wraps


    me>   class delegate_super:
    me>       """A method decorator that delegates part of the computation to the same
    me>       method on the ancestor class."""

    me>       _name = None
    me>       _owner = None

    me>       def __init__(self, meth):
    me>           self._meth = meth
    me>           @wraps(meth)
    me>           def wrapper(*args, **kwargs):
    me>               return self.delegator(*args, **kwargs)
    me>           self.wrapper = wrapper

    me>       def __get__(self, instance, owner):
    me>           return partial(self.wrapper, instance)

    me>       def __set_name__(self, owner, name):
    me>           self._owner = owner
    me>           self._name = name

    me>       def delegator(self, instance, *args, **kwargs):
    me>           result = self._meth(instance, *args, **kwargs)
    me>           if result is None:
    me>               result = getattr(super(self._owner, instance), self._name)(
    me>                   *args, **kwargs)
    me>           return result

    me>   class A:
    me>       def filter(self, element):
    me>           # the default implementation always returns True
    me>           return True


    me>   class B(A):
    me>       @delegate_super
    me>       def filter(self, element):
    me>           if element == 'foo':
    me>               return True
    me>           elif element == 'bar':
    me>               return False


    me>   class C(B):
    me>       @delegate_super
    me>       def filter(self, element):
    me>           if element == 'bar':
    me>               return True
    me>           else:
    me>               return super().filter(element)

The correct version is:

  class C(B):
      @delegate_super
      def filter(self, element):
          if element == 'bar':
              return True





More information about the Python-list mailing list