Skip to main content

我喜欢为各种事情打包的琐碎功能

项目描述

只是我喜欢随身携带的方便功能库。其他人可以随意复制这个库,但他们不应该依赖它。内容和 API 如有更改,恕不另行通知。

<nav class="contents" id="contents" role="doc-toc">

内容

</nav>

物化

reify是我从 Pylons 项目中偷来的一个装饰器,我喜欢经常使用它。

来自文档字符串:

用作类方法装饰器。它的操作几乎与 Python 的@property装饰器完全相同,但它在第一次调用后将其装饰的方法的结果放入实例 dict 中,从而有效地将其装饰的函数替换为实例变量。用 Python 的话来说,它是一个非数据描述符。

缓存的

cached是一个装饰器,它创建一个属性但缓存它的结果。它在功能上类似于 reify,但它动态地创建一个“私有”属性来缓存结果而不是弄乱描述符。这种方法与插槽兼容。我喜欢老虎机。

w

w是一个函数,它接受带有上下文管理器(如文件对象)的可迭代对象,并在其上下文管理器中从该可迭代对象中产生。

>>> # instead of this:
>>> with open('myfile.txt') as mf:
...     for line in mf:
...         # do something
...
>>> # you can do this:
>>> for line in w(open('myfile.txt')):
...     # do something
...

展平

flatten是一个函数,它接受一个可迭代对象作为参数并递归地从嵌套的可迭代对象中产生所有内容(字符串除外,它作为字符串产生)。可选的第二个参数是一个函数,用于在从它们产生之前将任何映射转换为可迭代对象(如果您想从它们的值或其他东西中产生)。

深度更新

从另一个字典更新字典,但在嵌套字典的情况下不会覆盖树的整个分支。我使用它将系统配置文件中的内容与用户配置文件结合起来。

>>> import libaaron
>>> a = {
...     "type": "foo",
...     "content": {
...         "bar": "baz",
...         "eggs": "spam"
...     }
... }
>>> b = {
...     "content": {
...         "ham": "sausage",
...         "bar": "lol"
...     }
... }
>>> libaaron.deepupdate(a, b)
>>> a
{
    'type': 'foo',
    'content': {
        'bar': 'lol',
        'eggs': 'spam',
        'ham': 'sausage'
     }
}

还有一个listextend标志,当设置为True时,如果两个字典中的值都是序列,则 a 中的序列将使用b 的内容进行扩展。如果字典 a b在某处有一个仅包含字符串的映射,则此函数可能会崩溃。

管道

pipe是一个普通函数,它接受一个初始值和任意数量的函数作为参数,以组合方式应用它们。它是这样定义的:

def pipe(value, *functions):
    for function in functions:
        value = function(value)
    return value

所以:

pipe(value, f, g, h) == h(g(f(value)))

这是为了避免一方面必须提出大量中间变量名称,另一方面是避免深度嵌套的函数调用。

管道

管道是管道上的一个包装器,它包含函数并允许您稍后应用初始参数。

pipline(f, g, h)(*args, **kwargs) == h(g(f(*args, **kwargs)))

fcompose

fcompose提供类似数学的函数组合。它与pipeline基本相同,但应用顺序相反。

# in math, this would look like `f ∘ g ∘ h`
fcompose(f, g, h)(*args, **kwargs) == f(g(h(*args, **kwargs)

请注意,管道fcompose 的工作方式并没有什么聪明之处。它们不是像functools.partial这样模拟高阶函数的类,它们只是普通的高阶函数,在管道上构建管道不会优化调用堆栈。

pmap , pfilterpreduce

pmap(f) == functools.partial(map, f)
pfilter(f) == functools.partial(filter, f)
preduce(f) == functools.partial(functools.reduce, f)

只是用于柯里化mapfilterreduce的便利函数,这在使用上述函数组合函数时非常有用。

允许这样的东西:

import sys
from libaaron import pipe, pmap, pfilter

shout_about_dogs = pipe(
    sys.stdin,
    pfilter(lambda line: "dog" in line.lower()),
    pmap(str.upper)
)

# similar to:
shout_about_dogs = (l.upper() for l in sys.stdin if dog in l.lower())

在这种情况下,理解语法显然更清晰。pipe对于更长的迭代管道很有用,如果将其分解,可能会变得不清楚。

相当中断

fairinterrupt是一个函数,它添加了一个信号处理程序,当脚本因键盘中断而停止时,该处理程序使堆栈跟踪静音。它可以选择在中断时打印一条消息。

lxml_little_iter

lxml_little_iter仅在lxml在环境中时可用。它用于迭代非常大的 xml 文件,在顶层具有许多相同类型的记录(在 JSON 中将是一个数组)。它用于迭代太大而无法放入内存的数据。

此生成器函数将所有*args**kwargs传递给 lxml.etree.iterparse并产生相同的(偶数,元素)元组。但是,当检索到下一个项目时,会清除上一个元素并删除所有以前的节点。因此,冲头被保存。

点字典

DotDict是 dict 的子类,它允许使用点语法获取项目。也许在反序列化 JSON 时用作object_hook 。

字节

PBytesint的子类,它有一个__str__,它显示将其解释为多个字节并形成人类可读的格式。它还可以解析字符串中的多个字节。

>>> print(PBytes(2134963))
2.0 MiB
>>> PBytes.from_str('35.8 KB')
PBytes(36659)
>>> PBytes.from_str('35.8 KB', decimal=True)
PBytes(35800)

在内部,它只是一个整数,所以你可以用它做任何整数运算。请注意,from_str不会尝试确定它是二进制还是十进制格式。默认为二进制。使用decimal=True 显式更改行为。

它还有一个human_readable方法,它返回一个数字和用于轻松构建替代表示的单位:

>>> PBytes(83629).human_readable()
(81.6689453125, 'K')
>>> '%d%s' % PBytes(83629).human_readable()
'81K'
>>> '%d%s' % PBytes(83629).human_readable(decimal=True)
'83K'

项目详情