我在文件(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
来呼叫bar
而不是async
,那就可以了。如何在async
内拨打baz
?
答案 0 :(得分:3)
好吧,我希望有人能回答这个问题,但是没有人能得到正确答案。
问题是在Python 3.5和3.6中,单词async
和await
是关键字,但有时只是。其他时候他们扮演标识符的角色。
await
唯一的关键字是在声明为async def
的函数内部。唯一一次async
是一个关键字,就在def
之前或在async def
函数之内。当然,在async def async(foo)
情况下,async
的第二次使用是尝试将其用作async def
内的标识符,因此它失败,因为它是关键字。
这有点奇怪,因为所有其他关键字始终是关键字。例如,您无法使用while
作为标识符。
这种情况将在Python 3.7中发生变化,async
和await
都是关键字,就像其他所有关键字一样。
在Python 3.5和3.6中就是这样,因为他们不想立刻在每个人身上弹出一个新关键字。当您添加新关键字时,很多人可能拥有与新关键字同名的标识符,因此这些标识符变为非法,人们必须更改其代码,并且可能会遇到各种奇怪的错误。
如何在async
函数中使用名为await
或async def
的标识符的答案是您没有。您必须使用getattr
或别名标识符引用的对象或以其他方式对其进行排列,以便您不会将async
函数中的await
或async def
用作任何内容除了他们在那里的关键词。
虽然transition plan section of PEP 492中的含义并未真正彻底解决,但有一点描述。
作为旁注,在Python中重新定义名称就好了。人们可能最好将def foo
视为foo = lambda
(除了lambdas仅限于Python中的单个表达式)。因此,为foo
分配一个新的函数值不会导致任何问题,并且简单且定义明确。
答案 1 :(得分:1)
错误的原因是您使用保留关键字async作为您的函数名称,所以当您尝试调用它时。它尝试调用async关键字而不是被同一关键字覆盖的函数。
要在目录中更清楚地展示这一点,请创建两个名为requests.py
的文件,另一个文件为test.py.
现在,如果您使用import requests
(python library)并使用任何它在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
在你的问题的后一种情况下也会发生同样的情况。