- 代码
# wraps的参数是原来的函数,修饰返回的函数
def _implicit_lookup(self, subroutine, arg_name): # feed 里面查找 animal
replacer = ArgumentReplacer(subroutine, arg_name)
@wraps(subroutine) # 换汤不换药,不认识了subroutine
def lookup_closure(*args, **kwargs):
with replacer.replace_and_call(args, kwargs) as replaced: # 【注意】不是*args, **kwargs
if self._should_be_replaced(replaced.value):
self._lookup_in_store_and_replace_argument(replaced)
return replaced.returned_value
return lookup_closure
- 对比
def a_new_decorator(a_func):
@wraps(a_func)
def wrapTheFunction(*args, **kwargs):
print("I am doing some boring work before executing a_func()")
a_func(*args, **kwargs) # 【注意】不是 a_func(args, kwargs)
print("I am doing some boring work after executing a_func()")
return wrapTheFunction
- 另一个不常见
https://github.com/edgedb/edgedb/blob/master/edb/common/value_dispatch.py
import functools
def value_dispatch(func):
"""Like singledispatch() but dispatches by value of the first arg.
Example:
@value_dispatch
def eat(fruit):
return f"I don't want a {fruit}..."
@eat.register('apple')
def _eat_apple(fruit):
return "I love apples!"
@eat.register('eggplant')
@eat.register('squash')
def _eat_what(fruit):
return f"I didn't know {fruit} is a fruit!"
An alternative to applying multuple `register` decorators is to
use the `register_for_all` helper:
@eat.register_for_all({'eggplant', 'squash'})
def _eat_what(fruit):
return f"I didn't know {fruit} is a fruit!"
"""
registry = {}
@functools.wraps(func)
def wrapper(arg0, *args, **kwargs):
try:
delegate = registry[arg0]
except KeyError:
pass
else:
return delegate(arg0, *args, **kwargs)
return func(arg0, *args, **kwargs)
def register(value):
def wrap(func):
if value in registry:
raise ValueError(
f'@value_dispatch: there is already a handler '
f'registered for {value!r}'
)
registry[value] = func
return func
return wrap
wrapper.register = register
return wrapper
@value_dispatch
def eat(fruit):
return f"I don't want a {fruit}..."
@eat.register('apple')
def _eat_apple(fruit):
return "I love apples!"
@eat.register('eggplant')
@eat.register('squash')
def _eat_what(fruit):
return f"I didn't know {fruit} is a fruit!"
res = _eat_apple('eggplant')
print(res)