繁体   English   中英

为什么在Python中存在涉及异步的怪异语法奇怪之处?

[英]Why does this weird syntax oddity involving async exist in Python?

我在文件( small.py )中有这小段代码:

def async(foo):
    pass

def bar(foo):
    pass

async def bar(foo):
    return None

async def async(foo):
    return None

当我执行python3.6 small.py它会发出以下投诉:

  File "small.py", line 7
    async def async(foo):
                  ^
SyntaxError: invalid syntax

如果我注释掉文件的最后两行,则可以正常工作。

这里发生了什么? 为什么完全没有拥有def async但不能确定有async def async

另外,我有这个文件( small2.py ):

def async(foo):
    pass

def bar(foo):
    return async(foo)

async def baz(foo):
    return async(foo)

当我做python2.6 small2.py我得到了:

  File "small2.py", line 8
    return async(foo)
               ^

但是,如果我将baz更改为call bar而不是async它就可以正常工作。 我如何在baz内部调用async

好吧,我希望有人能回答这个问题,但是没人能给出正确的答案。

问题在于,在Python 3.5和3.6中,单词asyncawait是关键字,但仅在某些时候。 其他时候,它们扮演标识符的角色。

唯一await时间是关键字在声明为async def的函数内部。 而且async是关键字的唯一时间是在def之前或在async def函数内部。 当然,在async def async(foo)情况下, async的第二种用法是尝试将其用作async def的标识符,因此它失败了,因为那里是一个关键字。

这有点怪异,因为所有其他关键字始终到处都是关键字。 例如,您不能将while用作标识符。

这种情况将在Python 3.7中改变,并且asyncawait到处都是关键字,就像其他所有关键字一样。

在Python 3.5和3.6中是这种方式,因为他们不想立即在每个人身上弹出新的关键字。 当您添加新关键字时,很多人可能会拥有与新关键字同名的标识符,因此这些标识符变得非法,人们不得不更改其代码,并可能会得到各种各样的奇怪错误,直到他们这样做为止。

关于如何在async def函数中使用名为asyncawait的标识符的答案是,您不会这样做。 您必须使用标识符所引用的对象的getattr或别名,或以其他方式对其进行排列,以便不要在async def函数中将单词asyncawait用作其附近的关键字。

尽管在PEP 492过渡计划部分中并未真正彻底地阐明其含义,但对此进行了一些描述。

附带说明一下,在Python中重新定义名称就可以了。 最好将def foo视为foo = lambda (除了lambda仅限于Python中的单个表达式)。 因此,为foo分配新的函数值不会造成任何问题,并且操作简单且定义明确。

错误的原因是您使用保留关键字async作为函数名称,因此无论何时尝试调用它。 它尝试调用async关键字,而不是调用已被该关键字覆盖的函数。

为了在目录中更清楚地说明这一点,请创建两个文件,一个文件名为requests.py另一个文件名为test.py. 现在,如果您使用import requestspython库 )并在test.py使用它的任何方法,它将抛出错误。 因为文件requests.py会覆盖库requests

同样的情况在这里发生。 您已使用名称async声明了一个函数。 另外,您稍后还声明了一个异步方法,该方法将使用名称async覆盖该方法。 因此,无论何时调用异步,它都会尝试调用异步方法。 由于async保留关键字 ,不再是已被覆盖的函数,因此它将报告错误。 要解决此问题,请将函数名称从异步更改为其他名称。

'''def async(foo): #overrides async coroutine hence now async refers to this function.
    pass'''

def asyn(foo):
     pass

def bar(foo):
    pass

async def bar(foo):
    return None

async def asyn(foo): # aync refers to above commented method in your code rather than coroutine.
    return None

您的问题的后一种情况也是如此。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM