标签: functools

functools.wraps不允许我用Python 3中的类包装函数

我想为一些将文件作为第一个参数的函数编写装饰器.装饰器必须实现上下文管理器协议(即将包装函数转换为上下文管理器),所以我想我需要用类包装函数.

我对装饰模式并不熟悉,之前从未实现过上下文管理器,但是我写的内容在Python 2.7中有效,如果我注释掉它,它也适用于Python 3.3 wraps.

from functools import wraps
def _file_reader(func):
    """A decorator implementing the context manager protocol for functions
    that read files."""
#   @wraps(func)
    class CManager:
        def __init__(self, source, *args, **kwargs):
            self.source = source
            self.args = args
            self.kwargs = kwargs
            self.close = kwargs.get('close', True)

        def __enter__(self):
            # _file_obj is a little helper that opens the file for reading
            self.fsource = _file_obj(self.source, 'r') 
            return func(self.fsource, *self.args, **self.kwargs)

        def __exit__(self, exc_type, exc_value, traceback):
            if self.close:
                self.fsource.close()
            return False …
Run Code Online (Sandbox Code Playgroud)

python decorator contextmanager python-3.x functools

6
推荐指数
1
解决办法
2256
查看次数

对具有常量但不可散列的对象的函数使用functools.lru_cache

是否可以functools.lru_cache用于缓存由functools.partial?创建的部分函数?

我的问题是一个带有可清洗参数的函数以及NumPy数组等不可清除的对象.

考虑这个玩具示例:

import numpy as np
from functools import lru_cache, partial

def foo(key, array):
    print('%s:' % key, array)
a = np.array([1,2,3])
Run Code Online (Sandbox Code Playgroud)

由于NumPy数组不可清除,因此不起作用:

@lru_cache(maxsize=None)
def foo(key, array):
    print('%s:' % key, array)
foo(1, a)
Run Code Online (Sandbox Code Playgroud)

正如所料,您会收到以下错误:

/Users/ch/miniconda/envs/sci34/lib/python3.4/functools.py in __init__(self, tup, hash)
    349     def __init__(self, tup, hash=hash):
    350         self[:] = tup
--> 351         self.hashvalue = hash(tup)
    352 
    353     def __hash__(self):

TypeError: unhashable type: 'numpy.ndarray'
Run Code Online (Sandbox Code Playgroud)

所以我的下一个想法是用来functools.partial摆脱NumPy数组(无论如何都是常量)

pfoo = partial(foo, array=a)
pfoo(2)
Run Code Online (Sandbox Code Playgroud)

所以现在我有一个只能使用hashable参数的函数,并且应该是完美的lru_cache.但是lru_cache在这种情况下可以使用吗?我不能用它作为包装函数而不是@lru_cache装饰器,可以吗? …

python python-3.x functools

6
推荐指数
2
解决办法
2711
查看次数

在heroku上部署python flask应用程序会给functools32带来错误

关于stackoverflow的第一个问题:D(因为我发现几乎所有东西直到现在).

我尝试将我的python应用程序部署到Heroku,但出现以下错误:

git push heroku master
Counting objects: 7036, done.
Compressing objects: 100% (3933/3933), done.
Writing objects: 100% (7036/7036), 10.97 MiB | 338.00 KiB/s, done.
Total 7036 (delta 2020), reused 7021 (delta 2014)
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Python app detected
remote: -----> Installing python-3.6.2
remote: -----> Installing pip
remote: -----> Installing requirements with pip
remote:        Collecting aniso8601==1.2.1 (from -r /tmp/build_3d7108e037a9a8803be5100bdc092768/requirements.txt (line 1))
remote:          Downloading aniso8601-1.2.1.tar.gz (62kB)
remote:        Collecting click==6.7 (from -r /tmp/build_3d7108e037a9a8803be5100bdc092768/requirements.txt (line …
Run Code Online (Sandbox Code Playgroud)

python heroku flask functools

6
推荐指数
1
解决办法
1033
查看次数

functools.wrapper - AttributeError: 'type' 对象的属性 '__doc__' 不可写

在执行下面的代码时,我得到AttributeError: attribute '__doc__' of 'type' objects is not writable.

from functools import wraps

def memoize(f):
    """ Memoization decorator for functions taking one or more arguments.
        Saves repeated api calls for a given value, by caching it.
    """
    @wraps(f)
    class memodict(dict):
       """memodict"""
       def __init__(self, f):
           self.f = f
       def __call__(self, *args):
           return self[args]
       def __missing__(self, key):
           ret = self[key] = self.f(*key)
           return ret
     return memodict(f)

@memoize
def a():
    """blah"""
    pass
Run Code Online (Sandbox Code Playgroud)

追溯:

from functools import wraps

def memoize(f):
    """ Memoization …
Run Code Online (Sandbox Code Playgroud)

decorator python-2.7 functools dictionary-missing

5
推荐指数
1
解决办法
6264
查看次数

更新类的属性时清除某些方法的 lru_cache?

我有一个带有 method/property 的对象multiplier。这个方法在我的程序中被调用了很多次,所以我决定使用lru_cache()它来提高执行速度。正如预期的那样,它要快得多:

以下代码显示了问题:

from functools import lru_cache

class MyClass(object):
    def __init__(self):
        self.current_contract = 201706
        self.futures = {201706: {'multiplier': 1000},
                        201712: {'multiplier': 25}}

    @property
    @lru_cache()
    def multiplier(self):
        return self.futures[self.current_contract]['multiplier']

CF = MyClass()
assert CF.multiplier == 1000

CF.current_contract = 201712
assert CF.multiplier == 25
Run Code Online (Sandbox Code Playgroud)

第二个assert失败,因为缓存值为 1000,因为lru_cache()不知道底层属性current_contract已更改。

更新 self.current_contract 时有没有办法清除缓存?

谢谢!

python synchronization caching lru functools

5
推荐指数
1
解决办法
1006
查看次数

python 的 functools.cmp_to_key 返回什么?

我在文档中得到了这一点,我可以使用 cmp_to_key 将旧式比较从 python2 转换为关键函数,例如在 python3 中,但我不知道返回的究竟是什么。例如:

def my_cmp(a, b):
    if(a == b):
        return 0
    elif(a < b):
        return -1
    else:
        return 1

my_key_fn = functools.cmp_to_key(my_cmp)
Run Code Online (Sandbox Code Playgroud)

然后每当我对任何数字调用 my_key_fn 时,结果是一个新函数的地址,每次调用都有一个新地址。例如:

In [49]: my_key_fn(1)
Out[49]: <functools.KeyWrapper at address...>
Run Code Online (Sandbox Code Playgroud)

我认为返回值会给我某种可以用作排序键的值。为什么我会得到一个函数包装器?

python functools

5
推荐指数
1
解决办法
925
查看次数

从函数内部禁用`functools.lru_cache`

我想要一个可以使用的函数functools.lru_cache,但默认情况下不能使用。我正在寻找一种使用函数参数的方法,该参数可用于禁用lru_cache. 目前,我有两个版本的功能,一个有lru_cache一个没有。然后我有另一个函数,它用一个参数包装这些函数,该参数可用于控制使用哪个函数

def _no_cache(foo):
    print('_no_cache')
    return 1


@lru_cache()
def _with_cache(foo):
    print('_with_cache')
    return 0


def cache(foo, use_cache=False):
    if use_cache:
        return _with_cache(foo)
    return _no_cache(foo)
Run Code Online (Sandbox Code Playgroud)

有没有更简单的方法来做到这一点?

python functools python-decorators

5
推荐指数
1
解决办法
879
查看次数

Python - 如何记忆部分对象?

我有一组以整数和函数作为参数的函数。我想把它们记下来。

我知道使用这个解决方案,我可以pickle对两组参数进行编码并记住编码值。然而,在这个特定的用例中,函数参数很大且恒定,我不想用lru_cache在程序运行过程中永远不会改变的函数参数占用空间。

有没有一种方法可以让我记住部分函数,​​其中我已经修复了函数参数并收到了仅采用可哈希参数的部分对象?我不知道如何将functools.lru_cache装饰器用作函数。

这是我在玩具示例上尝试过的方法。这不起作用;二项式树仍然会重新访问节点。

import functools
import logging


logging.basicConfig(level=logging.DEBUG)


def binomial_tree(x, y, fn):
    logging.debug(f"binomial_tree({x}, {y})")
    """Note: this does not recombine, and we can't memoize function."""
    if x == 10:
        return fn(x, y)
    else:
        return 0.5 * binomial_tree(x + 1, y, fn) + 0.5 * binomial_tree(x + 1, y + 1, fn)


def memoize_fn(fn):
    @functools.lru_cache(maxsize=None)
    def inner(*args, **kwargs):
        return fn(*args, **kwargs)
    return inner

memoized_binomial_tree = memoize_fn(functools.partial(binomial_tree, fn=lambda x, y: 10 * x * …
Run Code Online (Sandbox Code Playgroud)

python memoization functools

5
推荐指数
1
解决办法
820
查看次数

通过 GroupBy.agg 和命名聚合计算加权平均值

Pandas 0.25 版通过函数aggnamedtuples. 您需要按照文档描述传递列、聚合器对。它还说:

如果您的聚合函数需要额外的参数,请使用 functools.partial() 部分应用它们。

我想应用这个原则来获得加权平均值(除了简单的计数和平均值)。我的输入表是

import pandas as pd

t = pd.DataFrame({'bucket':['a', 'a', 'b', 'b', 'b'], 'weight': [2, 3, 1, 4, 3], 
                  'qty': [100, 500, 200, 800, 700]})
Run Code Online (Sandbox Code Playgroud)

我的查询失败了:

import functools
import numpy as np

t.groupby('bucket').agg(
        NR= ('bucket', 'count'),
        AVG_QTY= ('qty', np.mean),
        W_AVG_QTY= ('qty', functools.partial(np.average, weights='weight'))
   )
Run Code Online (Sandbox Code Playgroud)

带有错误消息:

TypeError: 1D weights expected when shapes of a and weights differ.
Run Code Online (Sandbox Code Playgroud)

我认为问题来自将参数固定为另一列而不是常量?如果没有使用的解决方法apply和返回 a 的 lambda 表达式,我怎样才能使这项工作Series

python group-by pandas functools

5
推荐指数
1
解决办法
2437
查看次数

在 Python 中创建动态部分可调用对象

我在 YAML 配置文件中定义了一个正则表达式。

为了方便起见,我将在这里使用字典:

rule_1 = {
    'kind': 'regex',
    'method': 'match',
    'args': None,
    'kwargs': {
        'pattern': "[a-z_]+",
        'flags': re.X,
        'string': 's_test.log',
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望能够在函数中解析该规则。

如果我们假设这些值不会改变,那么我可以做这样的事情。

导入模块:

import re
from operator import methodcaller
from functools import partial
Run Code Online (Sandbox Code Playgroud)

我下面的第一个函数能够适应所使用的正则表达式方法的变化:

def rule_parser_re_1(*, kind, method, args=None, kwargs=None):
    if args is None: args = []
    if kwargs is None: kwargs = {}
    mc = methodcaller(method, **kwargs)
    return mc(re)
Run Code Online (Sandbox Code Playgroud)

它按预期工作:

>>> rule_parser_re_1(**rule_1)
<re.Match object; span=(0, 6), match='s_test'>
Run Code Online (Sandbox Code Playgroud)

现在,假设在定义配置字典时我没有要解析的字符串。

例如,假设它是文件中的特定行,只能在运行时访问。

myfile = """
first line
second line …
Run Code Online (Sandbox Code Playgroud)

python functools

5
推荐指数
1
解决办法
183
查看次数