在python3.5中异步设置描述符 [英] Setting a descriptor in python3.5 asynchronously
问题描述
我可以写一个描述符返回一个可以等待的未来.
I can write a descriptor returning a future which could be awaited on.
class AsyncDescriptor:
def __get__(self, obj, cls=None):
# generate some async future here
return future
def __set__(self, obj, value):
# generate some async future here
return future
class Device:
attr=AsyncDescriptor()
device=Device()
现在我可以使用 value=await device.attr
在协程中获取值.
Now I can get the value in a coroutine with value=await device.attr
.
我将如何设置此属性?
await device.attr=5
-> 语法错误:无法分配给 await 表达式await setattr(device, 'attr', 5)
-> TypeError: object NoneType 不能用于 'await' 表达式device.attr=5
-> RuntimeWarning:协程__set__"从未被等待
await device.attr=5
-> SyntaxError: can't assign to await expressionawait setattr(device, 'attr', 5)
-> TypeError: object NoneType can't be used in 'await' expressiondevice.attr=5
-> RuntimeWarning: coroutine '__set__' was never awaited
推荐答案
您尝试做的事情是不可能的(使用 Python 3.5).
What you are trying to do is not possible (with Python 3.5).
虽然 __get__
返回 Future 可能是明智的,但 Python 3.5 根本不支持使 __set__
异步.__set__
的返回值被 Python 忽略,因为没有赋值的返回值".并且对 __set__
的调用始终是同步的.正如您已经注意到的那样,a = (b.c = 5)
实际上会引发 SyntaxError
.
While it may be sensible for __get__
to return a Future, making __set__
async is simply not supported by Python 3.5. The return value of __set__
is ignored by Python since there is no "return value" of assignments. And the call to __set__
is always synchronous. Something like a = (b.c = 5)
actually raises a SyntaxError
as you already noticed.
如果允许像 await device.attr = 5
这样的异步赋值,那么异步描述符可能会有一个单独的协议,即协程 __aget__
和 __aset__
作为特殊方法,类似于异步上下文管理器(async with
/__aenter__
)和异步迭代(async for
/__aiter__
).有关 async
PEP 492>/await
支持.
If async assignments like await device.attr = 5
were allowed, there would probably be a separate protocol for async descriptors, i.e. with coroutines __aget__
and __aset__
as special methods in analogy to async context manager (async with
/ __aenter__
) and async iteration (async for
/ __aiter__
). See PEP 492 for the design decisions behind the async
/ await
support.
还要注意 __get__
返回一个 future 不会使 __get__
成为一个协程.
Also note that __get__
returning a future does not make __get__
a coroutine.
如果没有进一步的上下文,您似乎想在描述符协议提供的属性访问抽象背后隐藏一些东西,最好明确地完成,但这当然取决于您.
Without further context, it looks like you want to hide something behind the attribute access abstraction provided by the descriptor protocol which should better be done explicitly, but that's up to you of course.
这篇关于在python3.5中异步设置描述符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!