Python: Decorators: How does the following code work?
Are the comments in the following code correct? Particularly the "instance =..." one?
# This does nothing.
class donothing(object):
def __init__(self, func):
"""
The 'func' argument is the function being decorated because in this
case, we're not instantiating the decorator class. Instead we are just
using the class object as a callable (a class is always callable as this
is how an instance is returned) to use as a decorator, which means that
it is being instantiated upon definition of the decorated function and
the decorated function is being passed in as an argument to the class's
__init__ method.
"""
self.func = func
def __call__(self, *args, **kwargs):
"""
The __call__ function is called when the decorated function is called
because the function has be eaten by the decorator class. Now it's up to
the this method to return a call to the original function. The arguments
are passed in as args, kwargs to be manipulated.
"""
# Returns original function call with original arguments.
return self.func(*args, **kwargs)
@donothing
def printer(text):
print(text)
printer('hello world')
# The printer function is now an alias for the donothing instance created, so
# the preceding was the same as:
#
# instance = donothing(printer)
# instance('hello world')
#
# Next example:
class checkforkeysinparams(object):
def __init__(self, required):
self.required = set(required)
def __call__(self, params):
def wrapper(params):
missing = self.required.difference(params)
if missing:
raise TypeError('Missing from "params" argument: %s' % ', '.join(sorted(missing)))
return wrapper
# Apply decorator class, passing in the __init__'s 'required' argument.
@checkforkeysi开发者_开发技巧nparams(['name', 'pass', 'code'])
def complex_function(params):
# Obviously these three are needed or a KeyError will be raised.
print(params['name'])
print(params['pass'])
print(params['code'])
# Create params to pass in. Note, I've commented out one of the required params.
params = {
'name': 'John Doe',
'pass': 'OpenSesame',
#'code': '1134',
}
# This call will output: TypeError: Missing from "params" argument: code
complex_function(params=params)
Yes perfect description, decorator donothing
decorates the function printer
and returns a object of class donothing
, so yes decorator simply boils down to this
x = donothing(func) # donothing is a class not function
and you can use it like this, if you wish to avoid @deco syntax.
so now x is an object, when you do x(), __call__
of that object is called and there it calls the function which was passed in __init__
edit:
Second decorator is wrong , because it only checks the parameter but never calls the function being passed
and function being passed to decorator is names params
but should be name something like func or better name
you can test that it does nothing by passing correct params
params = {
'name': 'John Doe',
'pass': 'OpenSesame',
'code': '1134',
}
complex_function(params=params)
it doesn't print the arguments as complex_function is supposed to do.
so correct decorator is
class checkforkeysinparams(object):
def __init__(self, required):
self.required = set(required)
def __call__(self, func):
def wrapper(params):
missing = self.required.difference(params)
if missing:
raise TypeError('Missing from "params" argument: %s' % ', '.join(sorted(missing)))
func(params)
return wrapper
In first example Class is being used as decorator itself, here the object of class checkforkeysinparams
is used as deocrator
hence function gets passed to __call__
of that object
精彩评论