杂项纯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次、指数衰减超时等),而无需更改您的代码。
========
.. 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 的哈希
算法 | 哈希摘要 | |
---|---|---|
SHA256 | b869af08570429d6e1e00ffc2c86d97647bf4a060abef2e30d1d1e822e034070 |
|
MD5 | 590c96d5e8a7c5ea67518ad7ac8fa2d5 |
|
BLAKE2b-256 | fb09f721dd16a5a1204b5f1a7712f27b68b52c7e141652392bcaa3304c0f5c7f |