我对 python 还不够了解,无法自己解决这个问题,所以这就是我想在这里尝试的原因。有没有办法让这些几乎相同的@wraps函数占用更少的空间?我总共有 5 个这样的东西,100 行 5 次同样的东西听起来很浪费。我最初在某个网站上找到过这个,但现在似乎找不到了。
功能:
def a_required(func):
@wraps(func)
def decorated_view(*args, **kwargs):
if request.method in EXEMPT_METHODS:
return func(*args, **kwargs)
elif current_app.config.get('LOGIN_DISABLED'):
return func(*args, **kwargs)
elif not current_user.is_authenticated or not current_user["Keys"]["A"]:
return current_app.login_manager.unauthorized()
return func(*args, **kwargs)
return decorated_view
def b_required(func):
@wraps(func)
def decorated_view(*args, **kwargs):
if request.method in EXEMPT_METHODS:
return func(*args, **kwargs)
elif current_app.config.get('LOGIN_DISABLED'):
return func(*args, **kwargs)
elif not current_user.is_authenticated or not current_user["Keys"]["B"]:
return current_app.login_manager.unauthorized()
return func(*args, **kwargs)
return decorated_view
Run Code Online (Sandbox Code Playgroud)
这是一个 Flask 网站,其页面只有拥有正确权限的用户才能访问。
我不明白如何functools.lru_cache处理对象实例。我假设该类必须提供一种__hash__方法。因此任何具有相同哈希值的实例都应该hit缓存。
这是我的测试:
from functools import lru_cache
class Query:
def __init__(self, id: str):
self.id = id
def __hash__(self):
return hash(self.id)
@lru_cache()
def fetch_item(item):
return 'data'
o1 = Query(33)
o2 = Query(33)
o3 = 33
assert hash(o1) == hash(o2) == hash(o3)
fetch_item(o1) # <-- expecting miss
fetch_item(o1) # <-- expecting hit
fetch_item(o2) # <-- expecting hit BUT get a miss !
fetch_item(o3) # <-- expecting hit BUT get a miss !
fetch_item(o3) # <-- expecting hit …Run Code Online (Sandbox Code Playgroud) 我有一个像下面这样的龙卷风方法,我试图装饰方法来缓存东西。我有以下设置
def request_cacher(x):
def wrapper(funca):
@functools.wraps(funca)
@asynchronous
@coroutine
def wrapped_f(self, *args, **kwargs):
pass
return wrapped_f
return wrapper
class PhotoListHandler(BaseHandler):
@request_cacher
@auth_required
@asynchronous
@coroutine
def get(self):
pass
Run Code Online (Sandbox Code Playgroud)
我收到错误,有AttributeError: 'PhotoListHandler' object has no attribute '__name__'
什么想法吗?
我正在尝试测试一个被记忆的方法lru_cache(因为它是一个昂贵的数据库调用)。和pytest-mock.
代码的简化版本是:
class User:
def __init__(self, file):
# load a file
@lru_cache
def get(self, user_id):
# do expensive call
Run Code Online (Sandbox Code Playgroud)
然后我正在测试:
class TestUser:
def test_get_is_called(self, mocker):
data = mocker.ANY
user = User(data)
repository.get(user_id)
open_mock = mocker.patch('builtins.open', mocker.mock_open())
open_mock.assert_called_with('/foo')
Run Code Online (Sandbox Code Playgroud)
但我收到以下错误:
TypeError: unhashable type: '_ANY'
Run Code Online (Sandbox Code Playgroud)
发生这种情况是因为functools.lru_cache需要存储的密钥是可散列的,即有一个方法__hash__或__cmp__实现。
我怎样才能在嘲笑者中嘲笑这些方法以使其工作?
我试过了
user.__hash__.return_value = 'foo'
Run Code Online (Sandbox Code Playgroud)
没有运气。
我有一个方法可以根据形状的名称和一些参数绘制一条线或任何形状的补丁,它工作正常:
def draw_a_shape(ax, is_patch_not_line, shapename, **kwargs):
...
Run Code Online (Sandbox Code Playgroud)
现在我需要有 30 多个函数,比如draw_a_square_patch,draw_an_ellipse_outline等等。我可以用一种简单的方式实现它们,如下所示,但这有点痛苦:
def draw_a_square_patch(ax, **kwargs):
draw_a_shape(ax=ax, is_patch_not_line=True, shapename='a_square', **kwargs)
def draw_a_square_outline(ax, **kwargs):
draw_a_shape(ax=ax, is_patch_not_line=False, shapename='a_square', **kwargs)
def draw_an_ellipse_patch(ax, **kwargs):
draw_a_shape(ax=ax, is_patch_not_line=True, shapename='an_ellipse', **kwargs)
def draw_an_ellipse_outline(ax, **kwargs):
draw_a_shape(ax=ax, is_patch_not_line=False, shapename='an_ellipse', **kwargs)
.........
Run Code Online (Sandbox Code Playgroud)
我想知道是否有办法使用循环来做到这一点,也许像setattr?我在下面添加了一个无效的代码,只是为了解释我的意思:
for shapename in ['a_circle', 'a_square', ...]:
for is_patch_not_line in [False, True]:
new_func_name = "draw_" + shapename + "_"
if is_patch_not_line:
new_func_name += "patch"
else:
new_func_name += "outline"
global.setattr(new_func_name, "ax, **kwargs", ...)
Run Code Online (Sandbox Code Playgroud) 我设法找到的所有解决方案都只在lru_cache. 但就我而言dir(functools),这表明这lru_cache确实存在于functoolswhilecache中!我该如何解决这个问题?