我想为一些将文件作为第一个参数的函数编写装饰器.装饰器必须实现上下文管理器协议(即将包装函数转换为上下文管理器),所以我想我需要用类包装函数.
我对装饰模式并不熟悉,之前从未实现过上下文管理器,但是我写的内容在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中是否有“对应物” functools.partial?
即我想避免的是写:
lambda x, y: f(x)
Run Code Online (Sandbox Code Playgroud)
但是我很想像我写的那样保留相同的属性(关键字参数,漂亮的代表):
from functools import partial
incr = partial(sum, 1)
Run Code Online (Sandbox Code Playgroud)
代替
incr = lambda x: sum(1, x)
Run Code Online (Sandbox Code Playgroud)
我知道这样的东西很容易写,但我想知道是否已经有一种忽略参数的标准方法。
一个常见的用例是 Qts 信号和插槽。
是否可以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装饰器,可以吗? …
我首先要强调的是,我已经非常广泛地搜索了Web和Python文档+ StackOverflow,并且没有设法找到这个问题的答案.我还要感谢任何花时间阅读本文的人.
正如标题所示,我正在用Python编写装饰器,我希望它为包装函数添加关键字参数(请注意:我知道如何向装饰器本身添加参数,这不是我要求的).
下面是我编写的一段代码的工作示例,它完全适用于Python 3(特别是Python 3.5).它使用装饰器参数,为包装函数添加关键字参数,还定义并向包装函数添加新函数.
from functools import wraps
def my_decorator(decorator_arg1=None, decorator_arg2=False):
# Inside the wrapper maker
def _decorator(func):
# Do Something 1
@wraps(func)
def func_wrapper(
*args,
new_arg1=False,
new_arg2=None,
**kwds):
# Inside the wrapping function
# Calling the wrapped function
if new_arg1:
return func(*args, **kwds)
else:
# do something with new_arg2
return func(*args, **kwds)
def added_function():
print("Do Something 2")
func_wrapper.added_function = added_function
return func_wrapper
return _decorator
Run Code Online (Sandbox Code Playgroud)
现在这个装饰器可以按以下方式使用:
@my_decorator(decorator_arg1=4, decorator_arg2=True)
def foo(a, b):
print("a={}, b={}".format(a,b))
def …Run Code Online (Sandbox Code Playgroud) 我想使用functools.partial将某个参数设置为常量,同时完全删除该参数。
让我用一个简单的例子来解释它。
from functools import partial
def f(a, b):
return a * b
g = partial(f, b=2)
Run Code Online (Sandbox Code Playgroud)
但是,此函数g仍然具有以下调用签名:
g?
Signature: g(a, *, b=1)
Call signature: g(*args, **kwargs)
Type: partial
String form: functools.partial(<function f at 0x7ff7045289d8>, b=1)
File: /opt/conda/envs/dev/lib/python3.6/functools.py
Docstring:
partial(func, *args, **keywords) - new function with partial application
of the given arguments and keywords.
Run Code Online (Sandbox Code Playgroud)
我当然可以使用lambda函数来做到这一点,例如:
def f(a, b):
return a * b
g = lambda a: f(a, b=2)
Run Code Online (Sandbox Code Playgroud)
具有正确的呼叫签名:
g?
Signature: g(a)
Docstring: <no docstring>
File: …Run Code Online (Sandbox Code Playgroud) 我一直在处理有关lambda函数及其无法成为pickled. 我经常在运行中使用lambda函数作为一次性使用函数,当我必须以函数形式单独重新创建简单的 lambda 函数以用于酸洗时,它会大大降低我的工作流程生产力。
有没有办法将 alambda及其所有参数转换为 中的function对象Python 3.6.1?
lambda_func = lambda x: x.split(" ")
def func(x):
return x.split(" ")
input_string = "Darth Plagueis was a Dark Lord of the Sith"
# Function Version
func(input_string)
# ['Darth', 'Plagueis', 'was', 'a', 'Dark', 'Lord', 'of', 'the', 'Sith']
lambda_func(input_string)
# ['Darth', 'Plagueis', 'was', 'a', 'Dark', 'Lord', 'of', 'the', 'Sith']
def lambda2func(lambda_func):
#...
return func_version
Run Code Online (Sandbox Code Playgroud) 关于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) 我正在使用 afunctools.lru_cache来提供给定输入* 的临时文件路径。但是,如果路径不再存在,我想删除/替换单个相应的键。该cache_clear()方法将是矫枉过正,cache_info()似乎没有帮助。
谢谢你的帮助!
*被缓存的方法将文件对象从 S3 流式传输到本地临时文件。
我遇到了一个特殊的行为functools.update_wrapper:它__dict__用被包装对象的覆盖对象的 - 这可能会妨碍它在嵌套装饰器时的使用。
举一个简单的例子,假设我们正在编写一个将数据缓存在内存中的装饰器类和另一个将数据缓存到文件的装饰器类。下面的示例演示了这一点(我使示例变得简短并省略了所有缓存逻辑,但我希望它能演示这个问题):
import functools
class cached:
cache_type = 'memory'
def __init__(self, fcn):
super().__init__()
self.fcn = fcn
functools.update_wrapper(self, fcn, updated=())
def __call__(self, *args):
print("Retrieving from", type(self).cache_type)
return self.fcn(*args)
class diskcached(cached):
cache_type = 'disk'
@cached
@diskcached
def expensive_function(what):
print("expensive_function working on", what)
expensive_function("Expensive Calculation")
Run Code Online (Sandbox Code Playgroud)
这个例子按预期工作 - 它的输出是
Retrieving from memory
Retrieving from disk
expensive_function working on Expensive Calculation
Run Code Online (Sandbox Code Playgroud)
然而,我花了很长时间才完成这项工作 - 起初,我没有在 functools.update_wrapper 调用中包含 'updated=()' 参数。但是,当忽略这一点时,嵌套装饰器将不起作用 - 在这种情况下,输出是
Retrieving from memory
expensive_function working on Expensive Calculation
Run Code Online (Sandbox Code Playgroud)
即外层装饰器直接调用最内层包装函数。原因(我花了一段时间才理解)是将包装器的属性 …
functools.partial我想知道这些和事实背后的故事 - 无论是声音设计还是继承的遗产 - inspect.signature(这里谈论 python 3.8)。
设置:
from functools import partial
from inspect import signature
def bar(a, b):
return a / b
Run Code Online (Sandbox Code Playgroud)
一切都从以下开始,这似乎符合咖喱标准。我们正在固定a位置3,a从签名中消失,它的值确实绑定到3:
f = partial(bar, 3)
assert str(signature(f)) == '(b)'
assert f(6) == 0.5 == f(b=6)
Run Code Online (Sandbox Code Playgroud)
如果我们尝试为 指定一个替代值a,f不会告诉我们我们得到了一个意外的关键字,而是告诉我们它有多个参数值a:
f = partial(bar, 3)
assert str(signature(f)) == '(b)'
assert f(6) == 0.5 == f(b=6)
Run Code Online (Sandbox Code Playgroud)
但现在如果我们b=3通过关键字修复,b则不会从签名中删除,它是对仅关键字的更改,我们仍然可以使用它(覆盖默认值,作为正常的默认值,这是我们在a之前无法做到的)案件):
f(a=2, …Run Code Online (Sandbox Code Playgroud)