Skip to content

Instantly share code, notes, and snippets.

@numberoverzero
Created June 10, 2014 21:41
Show Gist options
  • Select an option

  • Save numberoverzero/b88eb9fd0a204be45f4b to your computer and use it in GitHub Desktop.

Select an option

Save numberoverzero/b88eb9fd0a204be45f4b to your computer and use it in GitHub Desktop.
Chain class with special-casing for __call__, which __getattr__ won't handle (same with __getattribute__)
"""
Why is __call__ a special case?
https://docs.python.org/3.4/reference/datamodel.html#object.__getattribute__
> Note: This method may still be bypassed when looking up special methods as the result of implicit invocation via language syntax or built-in functions. See Special method lookup.
> In addition to bypassing any instance attributes in the interest of correctness, implicit special method lookup generally also bypasses the __getattribute__() method even of the object’s metaclass
"""
class Chain(object):
def __init__(self, objs):
# Private to avoid clashes when we setattr after compiling
self.__objs = objs
self.__call_partial = None
def __compile(self, method):
_next = noop
for obj in reversed(self.__objs):
func = getattr(obj, method, None)
if func:
_next = functools.partial(func, _next)
return _next
def __getattr__(self, name):
# Bind the compiled partial to self so we avoid
# __getattr__ overhead on the next call
func = self.__compile(name)
setattr(self, name, func)
return func
def __call__(self, *args, **kwargs):
'''special case because __getattr__ does not handle __call__'''
if not self.__call_partial:
self.__call_partial = self.__compile('__call__')
return self.__call_partial(*args, **kwargs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment