跳转到主要内容

杂项纯Python工具

项目描述

概述
========

.. image:: https://travis-ci.org/Infinidat/infi.pyutils.png?branch=master

*infi.pyutils* 是Python中各种任务的工具集。

内容
========

迭代工具
---------------

iterate
+++++++

*iterate* 是一种类似于Django风格的for循环,它对迭代集合提供方便的信息:

>>> from __future__ import print_function
>>> from infi.pyutils import iterate
>>> for iteration, element in iterate(range(3))
... print(element)
... print(iteration.first)
... print(iteration.counter0)
... print(iteration.counter1)
... print(iteration.last)
0
True
0
1
False
1
False
1
2
False
2
False
2
3
True

这对于生成器和其他可迭代对象也有效:

>>> list(iterate(i for i in range(3)))[-1][0].last
True

.. note:: 对于不是简单的迭代集合(即生成器或其他类型),为了确定最后一个元素,会进行一些预取操作

renumerate
++++++++++

*renumerate* 与 *enumerate* 类似,但方向相反。这对于就地从列表中删除元素很有用:

>>> 从infi.pyutils导入renumerate
>>> l = [1, 2, 3, 4]
>>> for index, element in renumerate(l)
... if element % 2 == 0
... unused = l.pop(index)
>>> l
[1, 3]

这也适用于生成器(尽管效率稍低)

>>> x = list(renumerate(i for i in range(3)))
>>> x
[(2, 2), (1, 1), (0, 0)]

*infi.pyutils*提供了一组混合类,使得对象可以根据单个键进行比较和散列:

>>> 从infi.pyutils导入ComparableByKey
>>> class MyComparableType(ComparableByKey)
... def __init__(self, value)
... super(MyComparableType, self).__init__()
... self.value = value
... def _get_key(self)
... return self.value
>>> MyComparableType("c") > MyComparableType("b")
True

反射
----------

方法映射
++++++++++

方法映射旨在用于以下重复模式
::

>>> class Handler(object)
... def handle_string(self, s)
... if s == 'some.string.1'
... return self._handle_string_1()
... elif s == 'some.string.2'
... return self._handle_string_2()
... raise NotImplementedError()

如果字符串可以合法地作为Python变量名,则可以在处理程序名称中插入字符串,然后使用getattr获取它们。不幸的是,这不可能用于任何字符串(并且也不够明确)。

使用方法映射非常简单

>>> 从infi.pyutils.method_map导入MethodMap
>>> class Handler(object)
... HANDLERS = MethodMap()
... @HANDLERS.registering('some.string.1')
... def _handle_string_1(self)
... return 1
... @HANDLERS.registering('some.string.2')
... def _handle_string_2(self)
... return 2
... def handle_string(self, s)
... handler = self.HANDLERS.get(s, None)
... if handler is None
... raise NotImplementedError()
... return handler()
>>> h = Handler()
>>> h.handle_string('some.string.1')
1
>>> h.handle_string('some.string.2')
2
>>> h.handle_string('bla') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last)
...
NotImplementedError

函子
--------
*infi.pyutils.functors*是一个用于处理函数或类似函数对象的实用程序包。

其他函子
++++++++++++++
*Always*用于始终返回一个值
::

>>> 从infi.pyutils.functors导入Always
>>> a = Always(5)
>>> a
<Always 5>
>>> a()
5
>>> a(1, 2, 3)
5

*Identity*是一个始终返回其单个参数的函子
::

>>> 从infi.pyutils.functors导入Identity
>>> Identity
<Identity>
>>> Identity(2)
2
>>> obj = object()
>>> Identity(obj) is obj
True

PASS
++++

PASS是一个'null函子'。您无论如何都可以调用它,它始终返回None:

>>> 从infi.pyutils.functors导入PASS
>>> PASS(1, 2, 3)
>>> PASS(666, a=2, c=4)

您还可以将其用作不执行任何操作的上下文管理器:

>>> with PASS
... pass

谓词
++++++++++
谓词是接受参数并返回True/False的函子
::

>>> 从infi.pyutils.predicates导入Predicate
>>> p = Predicate(lambda obj: obj is None)
>>> p(None)
True
>>> p(1)
False

AlwaysTrue和AlwaysFalse可用
::

>>> 从infi.pyutils.predicates导入AlwaysTrue, AlwaysFalse
>>> AlwaysTrue(1)
True
>>> AlwaysTrue()
True
>>> AlwaysFalse(1)
False
>>> AlwaysFalse(343)
False
>>> AlwaysFalse()
False

Identity
::

>>> 从infi.pyutils.predicates导入Identity
>>> is_none = Identity(None)
>>> is_none
<is None>
>>> is_none(None)
True
>>> is_none(1)
False

Equality
::

>>> 从infi.pyutils.predicates导入Equality
>>> class NeverEquals(object)
... def __eq__(self, other)
... return False
>>> equals_to_1 = Equality(1)
>>> equals_to_1
< == 1>
>>> equals_to_1(1)
True
>>> equals_to_1(2)
False
>>> obj = NeverEquals()
>>> Equality(obj)(obj) # 确保不是自等价
False

属性检查
::

>>> class SomeObject(object)
... pass
>>> a = SomeObject()
>>> a.x = 1
>>> a.y = 2
>>> a.z = 4
>>> b = SomeObject()
>>> b.x = 2
>>> b.y = 3
>>> b.z = 4
>>> from infi.pyutils.predicates import ObjectAttributes
>>> match = ObjectAttributes(z=4)
>>> match
<.z==4>
>>> match(a)
True
>>> match(b)
True
>>> match = ObjectAttributes(x=1, y=2)
>>> match(a)
True
>>> match(b)
False
>>> ObjectAttributes(missing_attribute=2)(a)
False

字典项检查
>>> d = dict(a=1, b=2)
>>> from infi.pyutils.predicates import DictionaryItems
>>> match = DictionaryItems(a=1)
>>> match
<['a']==1>
>>>
>>> match(d)
True
>>> match(dict(a=2, b=2))
False
>>> match(dict())
False
>>> match(dict(b=2))
False


逻辑聚合使用And、Or、Not
::

>>> from infi.pyutils.predicates import And, Or, Not
>>> obj = object()
>>> is_none_or_obj = Or(Identity(obj), Identity(None))
>>> is_none_or_obj #doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
Or(<is <object object at 0x...>>, <is None>)
>>> is_none_or_obj(obj)
True
>>> is_none_or_obj(None)
True
>>> is_none_or_obj(1)
False
>>> is_not_none = Not(is_none)
>>> is_not_none
<not <is None>>
>>> is_not_none(None)
False
>>> is_not_none(1)
True

延迟计算
----
*infi.pyutils.lazy* 提供了延迟计算和缓存的实用工具

cached_property 和 cached_method
+++++++++++++++++++++++++++++++++

>>> from infi.pyutils.lazy import cached_property
>>> class MyClass(object)
... called = False
... @cached_property
... def value(self)
... assert not self.called
... self.called = True
... return 1
>>> m = MyClass()
>>> m.value
1
>>> m.value
1

>>> from infi.pyutils.lazy import cached_method
>>> class MyClass(object)
... called = False
... @cached_method
... def get_value(self)
... assert not self.called
... self.called = True
... return 1
>>> m = MyClass()
>>> m.get_value()
1
>>> m.get_value()
1

装饰器工具
-------------------
The *infi.pyutils.decorators* 包含一个特别定制的 *wraps* 实现(functools.wraps 对应物),它保留了原始包装函数的信息。它还修补了 *inspect.getargspec* 和 IPython 的类似机制,以便在包装函数上显示正确的参数信息。因此,建议使用它而不是默认值。


上下文工具
-----------------
*infi.pyutils.contexts* 包含 *contextmanager*,它是 *contextlib.contextmanager* 的替代品,使用来自 *decorators* 的定制 *wraps* 实现。

导入工具
----------------
*infi.pyutils.importing* 包含 **import_file**,这是一个通过其名称导入模块的函数:

>>> from infi.pyutils.importing import *
>>> import tempfile, os
>>> temp_dir = tempfile.mkdtemp()
>>> filename = os.path.join(temp_dir, "my_file.py")
>>> with open(filename, "w") as f
... _ = f.write("a=2")
>>> module = import_file(filename)
>>> module.a
2

引用计数器
------------------
*infi.pyutils.reference_counter* 是一个支持依赖关系的引用计数器实现:

>>> from infi.pyutils.reference_counter import ReferenceCounter
>>> r = ReferenceCounter()
>>> r.get_reference_count()
0
>>> r.add_reference()
>>> r.get_reference_count()
1

可以通过依赖关系将多个引用计数器链式连接:

>>> r1 = ReferenceCounter()
>>> r2 = ReferenceCounter()
>>> r1.depend_on_counter(r2)
>>> r1.add_reference()
>>> r2.get_reference_count()
1

此外,作为便利,如果您向已经具有非零引用计数的计数器添加依赖关系,则依赖计数器也会自动增加:

>>> r1 = ReferenceCounter()
>>> r1.add_reference()
>>> r2 = ReferenceCounter()
>>> r1.depend_on_counter(r2)
>>> r2.get_reference_count()
1

您可以为引用计数降至零时调用的回调函数添加:

>>> r1 = ReferenceCounter()
>>> def callback(r)
... assert r is r1
... print("called!")
>>> r1.add_zero_refcount_callback(callback)
>>> r1.add_reference()
>>> r1.remove_reference()
called!

其他工具
---------------

recursive_getattr
+++++++++++++++++

>>>> 从infi.pyutils导入recursive_getattr
>>>> class Object(object)
... pass
>>>> a = Object()
>>>> a.b = Object()
>>>> a.b.c = 2
>>>> recursive_getattr(a, 'b.c')
2
>>>> recursive_getattr(a, 'b.d', 4)
4

Reprify
+++++++

**Reprify**旨在强制对不正确支持它们的对象执行__repr__/__str__:

>>>> 从infi.pyutils导入Reprify
>>> class SomeObject(object)
... pass
>>>> some_obj = SomeObject()
>>>> s = Reprify(some_obj, repr='some_repr_here', str='some_str_here')
>>>> repr(s)
'some_repr_here'
>>>> str(s)
'some_str_here'

同时保留身份和属性:

>>>> some_obj.attr = 2
>>>> s.attr
2
>>>> isinstance(s, SomeObject)
True

异常重试工具
-------------------------
**infi.pyutils.retry**包提供了一种机制,可以轻松定义何时以及如何重试失败的操作。它允许您将方法包装到您的类中,并插入错误处理策略(无限重试、重试N次、指数衰减超时等),而无需更改您的代码。

项目详情


下载文件

下载您平台上的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源分布

infi.pyutils-1.1.3.tar.gz (44.2 kB 查看哈希)

上传时间

支持者

AWSAWS 云计算和安全赞助商 DatadogDatadog 监控 FastlyFastly CDN GoogleGoogle 下载分析 MicrosoftMicrosoft PSF 赞助商 PingdomPingdom 监控 SentrySentry 错误日志 StatusPageStatusPage 状态页面