簡體   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