Python de la entrada a la práctica: generador de funciones

Tabla de contenido

1. La palabra clave de rendimiento

Dos, la aplicación de la expresión de rendimiento.

Tres, expresión ternaria, generación de listas, expresión generadora

3.1 Expresiones ternarias

3.2 Generación de listas

3.3 Expresiones generadoras


1. La palabra clave de rendimiento

Si el cuerpo de la función contiene la palabra clave yield, volver a llamar a la función no ejecutará el código del cuerpo de la función y el valor de retorno obtenido es el objeto generador.

>>> def my_range(start,stop,step=1):
...     print('start...')
...     while start < stop:
...         yield start
...         start+=step
...     print('end...')
... 
>>> g=my_range(0,3)
>>> g
<generator object my_range at 0x104105678>

 El generador tiene métodos _iter_ y _next_ incorporados , por lo que el generador en sí es un selector

>>> g.__iter__
<method-wrapper '__iter__' of generator object at 0x1037d2af0>
>>> g.__next__
<method-wrapper '__next__' of generator object at 0x1037d2af0>

>>> next(g) # 触发函数执行直到遇到yield则停止,将yield后的值返回,并在当前位置挂起函数
start...
0
>>> next(g) # 再次调用next(g),函数从上次暂停的位置继续执行,直到重新遇到yield...
1
>>> next(g) # 周而复始...
2
>>> next(g) # 触发函数执行没有遇到yield则无值返回,即取值完毕抛出异常结束迭代
end...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

 Dado que el objeto generador pertenece al iterador, debe ser posible usarlo para la selección de bucles, de la siguiente manera:

Con la palabra clave yield, tenemos una forma de implementar un selector personalizado. El rendimiento se puede usar para devolver un valor, pero a diferencia del retorno, la función finaliza una vez que encuentra un retorno, y el rendimiento puede guardar el estado de ejecución de la función y suspender la función para devolver múltiples valores.

Dos, la aplicación de la expresión de rendimiento.

yield puede tomar la forma de una expresión dentro de una función

>>> def eater():
...     print('Ready to eat')
...     while True:
...         food=yield
...         print('get the food: %s, and start to eat' %food)
... 

 El objeto generador que puede obtener la función sigue siendo el valor de envío del cuerpo de la función , de la siguiente manera

>>> g=eater() # 得到生成器对象
>>> g
<generator object eater at 0x101b6e2b0>
>>> next(g) # 需要事先”初始化”一次,让函数挂起在food=yield,等待调用g.send()方法为其传值
Ready to eat
>>> g.send('包子')
get the food: 包子, and start to eat
>>> g.send('鸡腿')
get the food: 鸡腿, and start to eat

Para rendimiento en forma de expresión, el objeto generador debe inicializarse una vez por adelantado, de modo que la función se suspenda en la posición de comida = rendimiento, esperando llamar al método g.send0 para pasar el valor del cuerpo de la función, g.send(Ninguno) es equivalente a next( g )

Podemos escribir un decorador para completar la inicialización del generador correspondiente para el rendimiento de todas las formas de expresión, de la siguiente manera

def init(func):
    def wrapper(*args,**kwargs):
        g=func(*args,**kwargs) #得到生成器(不会立刻有返回值)
        next(g)
        return g
    return wrapper
 
@init
def eater():
    print('Ready to eat')
    while True:
        food=yield
        print('get the food: %s, and start to eat' %food)

El rendimiento en forma de expresión también se puede usar para devolver valores múltiples, es decir, la forma de nombre de variable = valor de rendimiento, de la siguiente manera

>>> def eater():
...     print('Ready to eat')
...     food_list=[]
...     while True:
...         food=yield food_list
...         food_list.append(food)
... 
>>> e=eater()
>>> next(e)
Ready to eat
[]
>>> e.send('蒸羊羔')
['蒸羊羔']
>>> e.send('蒸熊掌')
['蒸羊羔', '蒸熊掌']
>>> e.send('蒸鹿尾儿')
['蒸羊羔', '蒸熊掌', '蒸鹿尾儿']

Tres, expresión ternaria, generación de listas, expresión generadora

3.1 Expresiones ternarias

res = 条件成立时返回的值 if 条件 else 条件不成立时返回的值

3.2 Generación de listas

Por supuesto, además de las listas, también hay diccionarios. Tenga en cuenta que () no genera tuplas, ¡sino generadores!

egg_list=['鸡蛋%s' %i for i in range(10)]

3.3 Expresiones generadoras

Hay dos formas de crear un objeto generador, una es llamar a una función con la palabra clave yield y la otra es una expresión generadora, que tiene el mismo formato gramatical que la generación de la lista, solo necesita reemplazar la boca con (), eso es :

>>> [x*x for x in range(3)]
[0, 1, 4]
>>> g=(x*x for x in range(3))
>>> g
<generator object <genexpr> at 0x101be0ba0>

En comparación con la generación de listas, la ventaja de la expresión del generador es, naturalmente, ahorrar memoria (¡solo se genera un valor en la memoria a la vez)!

>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g) #抛出异常StopIteration

Si queremos leer la cantidad de bytes de un archivo grande, debe hacerse en función de la expresión del generador

with open('db.txt','rb') as f:
    nums=(len(line) for line in f)
    total_size=sum(nums) # 依次执行next(nums),然后累加到一起得到结果=

Supongo que te gusta

Origin blog.csdn.net/weixin_43507744/article/details/126571993
Recomendado
Clasificación