目录
前言
最近在写项目中,用到了luigi,并且对luigi的scheduler要做一些改造。看luigi的源码时,发现了一个用到all的场景,感觉挺不过错的,特此记录下来。
其实下面我摘自源码的一段代码更值得去学习,动态检测你输入的参数是否合法
那么,本文还是先说all和any的用法。最后再上应用例子
一、all和any的用法
1、all的用法
语法
all(iterable)
all() 函数用于判断给定的可迭代参数 iterable
中的所有元素是否不为 0、''、False 或者 iterable 为空,
如果是返回 True,否则返回 False。
可以简单的记忆为,iterable里面的参数全都为真。注意:如果iterable本身为空,则返回True。
例子
>>> all([])
True
>>> all({})
True
>>> all(set())
True
>>> all([1,2,3,4])
True
>>> all([1,2,3,4,0])
False
>>> all([1,2,3,4,""])
False
>>> all([1,2,3,4,None])
False
2、any的用法
语法
any(iterable)
any() 函数用于判断给定的可迭代参数 iterable
iterable中元素有一个不为空就返回True,空指的是None、"",0
可以简单的记忆为,iterable里面的只要一个为真,就返回True。注意:iterable本身为空,返回false
>>> any([])
False
>>> any([1,2,3,4,0])
True
>>> any([1,0,0,0])
True
>>> any([0,0,0,0])
二、luigi源码中的活用all的实例
在luigui的scheduler源码中,提供了外界访问的api,用来与luigid server交互。为了能够检测出用户传入的参数是否合法,提供了一个 rpc_method的装饰器,加在每个路由函数上,用来判定。如下
import functools
RPC_METHODS = {}
def rpc_method(**request_args):
def _rpc_method(fn):
# If request args are passed, return this function again for use as
# the decorator function with the request args attached.
args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = inspect.getfullargspec(fn)
assert not varargs
first_arg, *all_args = args
assert first_arg == 'self'
defaults = dict(zip(reversed(all_args), reversed(defaults or ())))
required_args = frozenset(arg for arg in all_args if arg not in defaults)
fn_name = fn.__name__
@functools.wraps(fn)
def rpc_func(self, *args, **kwargs):
actual_args = defaults.copy()
actual_args.update(dict(zip(all_args, args)))
actual_args.update(kwargs)
if not all(arg in actual_args for arg in required_args):
raise TypeError('{} takes {} arguments ({} given)'.format(
fn_name, len(all_args), len(actual_args)))
return self._request('/api/{}'.format(fn_name), actual_args, **request_args)
RPC_METHODS[fn_name] = rpc_func
return fn
return _rpc_method
@rpc_method()
def task_list(self, status='', upstream_status='', limit=True, search=None, max_shown_tasks=None,**kwargs):
return "ok"
这里我把task_list函数功能给去掉了,以便能够关注我们要看rpc_method装饰器。
args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = inspect.getfullargspec(fn)
inspect.getfullargspec(fn)会获取fn函数的所有参数,返回一个元组。以下是对几个参数的解释
(args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations).
'args' is a list of the parameter names.
'varargs' and 'varkw' are the names of the * and ** parameters or None.
'defaults' is an n-tuple of the default values of the last n parameters.
'kwonlyargs' is a list of keyword-only parameter names.
'kwonlydefaults' is a dictionary mapping names from kwonlyargs to defaults.
'annotations' is a dictionary mapping parameter names to annotations.
rpc_method 函数其实分别两个步骤,如下是第一个步骤,获取到传入的fn函数的必传参数和非必传参数。
args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = inspect.getfullargspec(fn)
assert not varargs
first_arg, *all_args = args
assert first_arg == 'self'
defaults = dict(zip(reversed(all_args), reversed(defaults or ())))
required_args = frozenset(arg for arg in all_args if arg not in defaults)
fn_name = fn.__name__
第二个步骤也就是下面的代码,表示,将rpc_fun函数返回给当前被@rpc_method装饰的函数,并将其记录到 RPC_METHEAD字典中。
@functools.wraps(fn)
def rpc_func(self, *args, **kwargs):
actual_args = defaults.copy()
actual_args.update(dict(zip(all_args, args)))
actual_args.update(kwargs)
if not all(arg in actual_args for arg in required_args):
raise TypeError('{} takes {} arguments ({} given)'.format(
fn_name, len(all_args), len(actual_args)))
return self._request('/api/{}'.format(fn_name), actual_args, **request_args)
RPC_METHODS[fn_name] = rpc_func
return fn
而在rpc_fun中用到了 all 方法,他的作用是 检测当前传入的参数 是否满足了 需要传入的参数要求。使用all方法就表示必须全部满足,缺一不可。
if not all(arg in actual_args for arg in required_args):
raise TypeError('{} takes {} arguments ({} given)'.format(
fn_name, len(all_args), len(actual_args)))