funcutils - functools 修正

Python的内置功能 functools 模块在Python的一流函数支持之上构建了几个有用的实用程序。 funcutils 大体上保持相同的风格,添加和修正了Python的标准元编程工具。

装饰

Decorators 都是Python最优雅和最简洁的语言特性之一,Bolton添加了一个特殊的功能,使它们变得更加强大。

boltons.funcutils.wraps(func, injected=None, expected=None, **kw)[源代码]

装饰器工厂将UPDATE_WRAPPER()应用于包装器函数。

仿照内置 functools.wraps() 。返回一个修饰符,该修饰符以修饰后的函数作为包装参数,并将参数作为其余参数,来调用UPDATE_WRapper()。默认参数与UPDATE_WRAPPER()相同。这是一个方便的函数,可以简化将Partial()应用到UPDATE_WRAPPER()的过程。

与UPDATE_WRAPPER的文档中的示例相同,但使用了Wraps:

>>> from boltons.funcutils import wraps
>>>
>>> def print_return(func):
...     @wraps(func)
...     def wrapper(*args, **kwargs):
...         ret = func(*args, **kwargs)
...         print(ret)
...         return ret
...     return wrapper
...
>>> @print_return
... def example():
...     '''docstring'''
...     return 'example return value'
>>>
>>> val = example()
example return value
>>> example.__name__
'example'
>>> example.__doc__
'docstring'

功能建构

函数是用Python编程的关键,有时甚至会出现必须用Python构造Python函数的情况。值得庆幸的是,Python是一个足够动态的工具,足以使这一切成为可能。boltons让这一切变得很容易。

class boltons.funcutils.FunctionBuilder(name, **kw)[源代码]

FunctionBuilder类型提供了一个接口,用于基于现有函数或从头开始以编程方式创建新函数。

值在构造时传入或设置为实例上的属性。有关基于现有函数创建新函数的信息,请参见 from_func() 类方法。在任何时候, get_func() 可以根据配置的值调用以获取新编译的函数。

>>> fb = FunctionBuilder('return_five', doc='returns the integer 5',
...                      body='return 5')
>>> f = fb.get_func()
>>> f()
5
>>> fb.varkw = 'kw'
>>> f_kw = fb.get_func()
>>> f_kw(ignored_arg='ignored_val')
5

请注意,在Python3中,函数签名本身发生了很大的变化,因此有几个参数仅适用于Python3中的FunctionBuilder。 name 构造函数的所有参数都是关键字参数。

参数:
  • name (str) -- 函数的名称。

  • doc (str) -- Docstring 对于该函数,默认为空。

  • module (str) -- 从中导入此函数的模块的名称。默认为无。

  • body (str) -- 表示函数体的代码的字符串版本。默认为 'pass' ,这将导致一个不执行任何操作的函数并返回 None

  • args (list) -- 参数名称列表,默认为空列表,表示无参数。

  • varargs (str) -- 位置参数的通用变量的名称。例如,如果结果函数要具有 *args 在签名里。默认为无。

  • varkw (str) -- 关键字参数的通用变量的名称。例如,如果结果函数要具有 **kwargs 在签名里。默认为无。

  • defaults (tuple) -- 包含具有默认值的参数的默认参数值的元组。

  • kwonlyargs (list) -- 仅作为关键字参数有效的参数名称。 Python 3 only.

  • kwonlydefaults (dict) -- 贴图,与法线相同 defaults ,但仅适用于 kwonlyargsPython 3 only.

  • annotations (dict) -- 类型提示的映射等。 Python 3 only.

  • filename (str) -- 将出现在回溯中的文件名。默认为“boltons.funcutils.FunctionBuilder”。

  • indent (int) -- 用于缩进函数的空格数 body 。值小于1将导致错误。

  • dict (dict) -- 应添加到使用此FunctionBuilder编译的函数的任何其他属性。

所有这些参数还可以作为属性使用,这些属性可以根据需要进行更改。

add_arg(arg_name, default=NO_DEFAULT, kwonly=False)[源代码]

使用可选参数添加参数 default (默认为 funcutils.NO_DEFAULT )。经过 kwonly=True 添加仅限关键字的参数

classmethod from_func(func)[源代码]

基于现有函数创建新的FunctionBuilder实例。原始函数不会被存储或修改。

get_defaults_dict()[源代码]

获取带有缺省值和各自值的函数参数词典。

get_func(execdict=None, add_source=True, with_dict=True)[源代码]

根据FunctionBuilder的当前值编译并返回新函数。

参数:
  • execdict (dict) -- 表示应进行编译的范围的词典。默认情况下为空判决。

  • add_source (bool) -- 是否将使用的源添加到特殊 __source__ 属性添加到结果函数上。默认为True。

  • with_dict (bool) -- 添加任何自定义属性(如果适用)。默认为True。

若要查看用法示例,请参见 wraps()

get_sig_str(with_annotations=True)[源代码]

以字符串形式返回函数签名。

在Python2上忽略With_Annotation。在Python3上,如果将其设置为False,则签名将省略注释。

remove_arg(arg_name)[源代码]

从此FunctionBuilder的参数列表中删除参数。结果函数在每次调用此函数时将少一个参数。

参数:

arg_name (str) -- 要删除的参数的名称。

引发了一个 ValueError 如果论据不存在。

改进 partial

boltons.funcutils.partial

CachedInstancePartial 的别名

class boltons.funcutils.InstancePartial[源代码]

functools.partial 对于使用Python强大的一流函数的任何人来说,都是极大的便利。它允许开发人员集中讨论并逐步为各种用例创建更简单的可计算工具。

不幸的是,在它的有用性方面有一个很大的差距:方法。部分参数不会被绑定为方法,并自动将引用传递给 self 。这个 InstancePartial 类型通过继承 functools.partial 并实现必要的描述符协议。在实现或使用方面没有其他区别。 CachedInstancePartial ,具有相同的能力,但效率略高一些。

class boltons.funcutils.CachedInstancePartial[源代码]

这个 CachedInstancePartial 实际上与 InstancePartial ,添加了对方法用法的支持 functools.partial ,只是在第一次访问时,它将绑定方法缓存在关联的对象上,加快了以后访问的速度,并使方法调用开销与非``部分``方法大致相同。

请参阅 InstancePartial 文档字符串以获取更多详细信息。

其他元编程

boltons.funcutils.copy_function(orig, copy_dict=True)[源代码]

返回函数的浅表副本,包括代码对象、全局变量、闭包等。

>>> func = lambda: func
>>> func() is func
True
>>> func_copy = copy_function(func)
>>> func_copy() is func
True
>>> func_copy is not func
True
参数:
  • orig (function) -- 要复制的函数。必须是函数,而不是任何方法或Callable。

  • copy_dict (bool) -- 还要复制函数实例上设置的所有属性。默认为 True

boltons.funcutils.dir_dict(obj, raise_exc=False)[源代码]

将属性名称的字典返回给给定对象的值。不像 obj.__dict__ ,此函数返回对象的所有属性,包括父类上的属性。

boltons.funcutils.mro_items(type_obj)[源代码]

获取类型并返回遍及类型层次结构中所有类变量的迭代器(考虑MRO)。

>>> sorted(set([k for k, v in mro_items(int) if not k.startswith('__') and 'bytes' not in k and not callable(v)]))
['denominator', 'imag', 'numerator', 'real']
boltons.funcutils.format_invocation(name='', args=(), kwargs=None, **kw)[源代码]

在给定名称、位置参数和关键字参数的情况下,格式化基本的Python风格的函数调用。

>>> print(format_invocation('func', args=(1, 2), kwargs={'c': 3}))
func(1, 2, c=3)
>>> print(format_invocation('a_func', args=(1,)))
a_func(1)
>>> print(format_invocation('kw_func', kwargs=[('a', 1), ('b', 2)]))
kw_func(a=1, b=2)
boltons.funcutils.format_exp_repr(obj, pos_names, req_names=None, opt_names=None, opt_key=None)[源代码]

基于属性名呈现对象的表达式样式的REPR,这些属性名被假定与初始值设定项的参数排成一列。

>>> class Flag(object):
...    def __init__(self, length, width, depth=None):
...        self.length = length
...        self.width = width
...        self.depth = depth
...

这是我们的Flag对象,下面是它的一些示例表示:

>>> flag = Flag(5, 10)
>>> print(format_exp_repr(flag, ['length', 'width'], [], ['depth']))
Flag(5, 10)
>>> flag2 = Flag(5, 15, 2)
>>> print(format_exp_repr(flag2, ['length'], ['width', 'depth']))
Flag(5, width=15, depth=2)

通过选择位置名称、请求名称、选项名称和选项密钥,您可以微调REPR的外观。

参数:
  • obj (object) -- 将使用其类型名称并检查其属性的对象

  • pos_names (list) -- 将在输出REPR中呈现为位置参数的属性名称的必需列表。

  • req_names (list) -- 将始终出现在输出REPR的关键字参数中的属性名称列表。默认为无。

  • opt_names (list) -- 可能出现在输出REPR的关键字参数中的属性名列表,前提是它们将 opt_key 检查完毕。默认为无。

  • opt_key (callable) -- 检查opt_name是否应该出现在epr中的函数或可调用对象。默认设置为 None -检查。

boltons.funcutils.format_nonexp_repr(obj, req_names=None, opt_names=None, opt_key=None)[源代码]

设置非表达式样式引用的格式

一些对象表示看起来像对象实例化,例如App(r= [], mw=[] )。

这对于其状态往返的较小、较低级别的对象是有意义的。但是很多对象都包含不往返的值,比如类型和函数。

对于这些对象,有一种非表达式样式的REPR,它模仿了的Python的默认样式,以生成如下所示的REPR:

>>> class Flag(object):
...    def __init__(self, length, width, depth=None):
...        self.length = length
...        self.width = width
...        self.depth = depth
...
>>> flag = Flag(5, 10)
>>> print(format_nonexp_repr(flag, ['length', 'width'], ['depth']))
<Flag length=5 width=10>

如果未指定或设置任何属性,则使用id,这与Python的内置行为相似。

>>> print(format_nonexp_repr(flag))
<Flag id=...>