首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >异步初始化参数时将参数传递给python类

异步初始化参数时将参数传递给python类
EN

Stack Overflow用户
提问于 2018-09-16 22:29:39
回答 2查看 2K关注 0票数 2

我看了这个答案,在那里他们解释了如何用__await__方法异步初始化类。问题是:是否有可能在等待类初始化时传递参数,就像同步初始化类一样?

换句话说,我希望能够做my_class = await MyClass(my_parameter),但是我无法使它以任何方式工作。

我是不是应该回到使用经典的__init__,比如在这个答案

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-09-16 22:37:06

你应该只使用__init__。您首先创建一个常规类实例,然后等待该实例。这是两个不同的行动。

例如,您可以先创建实例,然后单独地等待它:

代码语言:javascript
复制
my_class = MyClass(my_parameter)
result_from_coroutine = await my_class

或者您可以从它创建一个任务,并让事件循环执行它

代码语言:javascript
复制
my_class = MyClass(my_parameter)
task = asyncio.create_task(my_class)  # the loop will await the task
# ...
if task.done():
    result_from_coroutine = task.result()

__await__方法是await或事件循环用来驱动协同线的方法。同样的分离也适用于coroutine函数(用async def定义);当您调用它们时,它们也会创建一个新的coroutine对象,您不必立即等待它们。您可以在其他时间对结果使用await

如果您正在寻找异步实例创建,那么您可以通过将方法设置为一个协同机制来破解这个问题:

代码语言:javascript
复制
>>> class Async:
...     async def __new__(cls):
...         instance = super().__new__(cls)
...         return instance
...
>>> Async()
<coroutine object Async.__new__ at 0x103654148>

在协同线上等待将创建实际实例并返回它。

考虑到这确实意味着__init__方法将被跳过;后者只有在__new__方法直接返回类的实例(或子类)时才会调用,而coroutine不是这样的实例。您必须亲自明确地这样做:

代码语言:javascript
复制
class Async:
    async def __new__(cls, *args, **kwargs):
        instance = super().__new__(cls)
        instance.__init__(*args, **kwargs)
        return instance

此时,您也可以决定将__init__方法作为一个协同线。

请注意,这确实有悖常理。我会把呼叫依赖的协同线推迟到稍后的时间。

例如,您只需将参数存储到实例上的类,并在等待实例时使用这些参数(通过调用__await__ ),就像链接到建议执行的post一样。

票数 2
EN

Stack Overflow用户

发布于 2018-09-17 06:53:51

换句话说,我希望能够做my_class = await MyClass(my_parameter),但是我无法使它以任何方式工作。

通过实现MyClass,您可以使__await__成为可接受的

代码语言:javascript
复制
class MyClass:
    def __init__(self, delay):
        self.delay = delay

    async def __await__(self):
        await asyncio.sleep(self.delay)

asyncio.run(MyClass(2)) # sleeps 2 seconds

链接答案中的代码做了类似的事情,但是它更复杂,因为它假设__init__本身需要await。如果情况并非如此,而且您的__init__实际上是微不足道的,但是您希望返回的实例是可接受的,则不需要增加拆分初始化的复杂性。

注意:尽管是推荐asyncio.run()仍然被标记为临时的。在上面的例子中,可以很容易地用run_until_complete替换它。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52358908

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档