python常見的幾種函數:
1、普通函數
def function():
return 1
2、生成器函數
def generator():
yield 1
3、異步函數(協程)
async def async_function():
return 1
4、異步生成器
async def async_generator():
yield 1
協程需要通過其他方式來驅動,因此可以使用這個協程對象的send方法給協程發送一個值,
try:
async_function().send(None)
except StopIteration as e:
print(e.value)
#1
#通過上面的方式來新建一個run函數來驅動協程函數:
def run(coroutine):
try:
coroutine.send(None)
except StopIteration as e:
return e.value
#在協程函數中,可以通過await語法來掛起自身的協程,並等待另一個協程完成直到返回結果:
async def async_function():
print(0)
return 1
async def await_coroutine():
result = await async_function()
print(result)
run(await_coroutine())
要注意的是,await語法只能出現在通過async修飾的函數中,否則會報SyntaxError錯誤。
而且await後面的對象需要是一個Awaitable,或者實現了相關的協議。
查看Awaitable抽象類的代碼,表明了只要一個類實現了__await__方法,那麼通過它構造出來的實例就是一個Awaitable:
class Awaitable(metaclass=ABCMeta):
__slots__ = ()
@abstractmethod
def __await__(self):
yield
@classmethod
def __subclasshook__(cls, C):
if cls is Awaitable:
return _check_methods(C, "__await__")
return NotImplemented
而且可以看到,Coroutine類也繼承了Awaitable,而且實現了send,throw和close方法。所以await一個調用異步函數返回的協程對象是合法的。
class Coroutine(Awaitable):
__slots__ = ()
@abstractmethod
def send(self, value):
...
@abstractmethod
def throw(self, typ, val=None, tb=None):
...
def close(self):
....
@classmethod
def __subclasshook__(cls, C):
if cls is Coroutine:
return _check_methods(C, '__await__', 'send', 'throw', 'close')
return NotImplemented