我想为一些将文件作为第一个参数的函数编写装饰器.装饰器必须实现上下文管理器协议(即将包装函数转换为上下文管理器),所以我想我需要用类包装函数.
我对装饰模式并不熟悉,之前从未实现过上下文管理器,但是我写的内容在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) 是否可以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装饰器,可以吗? …
关于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) 在执行下面的代码时,我得到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) 我有一个带有 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 时有没有办法清除缓存?
谢谢!
我在文档中得到了这一点,我可以使用 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)
我认为返回值会给我某种可以用作排序键的值。为什么我会得到一个函数包装器?
我想要一个可以使用的函数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)
有没有更简单的方法来做到这一点?
我有一组以整数和函数作为参数的函数。我想把它们记下来。
我知道使用这个解决方案,我可以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) Pandas 0.25 版通过函数agg和namedtuples. 您需要按照文档描述传递列、聚合器对。它还说:
如果您的聚合函数需要额外的参数,请使用 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?
我在 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) functools ×10
python ×9
decorator ×2
python-3.x ×2
caching ×1
flask ×1
group-by ×1
heroku ×1
lru ×1
memoization ×1
pandas ×1
python-2.7 ×1