类协程的一部分不是协程。为什么?

class Foo:
    async def foo(self, a):
        return a

async def bar(b):
    return b

asyncio.iscoroutinefunction(functools.partial(bar, 1)) # returns True, OK
asyncio.iscoroutinefunction(functools.partial(Foo().foo, 1)) # returns False, WHY???

我需要找到一种方法将类中的协程包装成部分的,这样结果也是一个协程。我怎么做?

回答

为什么是inspect 模块检查这个的方式。

def iscoroutinefunction(obj):
    """Return true if the object is a coroutine function.
    Coroutine functions are defined with "async def" syntax.
    """
    return _has_code_flag(obj, CO_COROUTINE)

如果我们看一下定义为_has_code_flag

def _has_code_flag(f, flag):
    """Return true if ``f`` is a function (or a method or functools.partial
    wrapper wrapping a function) whose code object has the given ``flag``
    set in its flags."""
    while ismethod(f):
        f = f.__func__
    f = functools._unwrap_partial(f)
    if not isfunction(f):
        return False
    return bool(f.__code__.co_flags & flag)

我们看到它首先尝试解包绑定方法并获取其.func属性(包含函数对象),然后解包partial. 最后,如果结果不是函数返回,False否则返回对底层函数__code__属性进行标志检查的结果。

问题是while ismethod(f)它什么都不做,因为那时它仍然是一个partial对象。然后解开后,如果从partialisfunction回报率False,因为它仅仅是一个绑定的方法存在。

这就是为什么。我不知道这是否可以被视为错误,或者是否是设计使然。文档字符串在其描述中_has_code_flag遗漏了functools.partial包装方法这一事实让我相信这是设计使然。

但是,您可以借用functools._unwrap_partial并使用他们coroutine通过检查.func属性来检查a 的方法。

def _unwrap_partial(func):
    while isinstance(func, partial):
        func = func.func
    return func

取自这个答案:

def iscoroutinefunction_or_partial(object):
    while isinstance(object, functools.partial):
        object = object.func
    return inspect.iscoroutinefunction(object)


以上是类协程的一部分不是协程。为什么?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>