La comprensión en profundidad de los generadores de Python y el generador iterador iterador

generadorgenerator

A veces vamos a utilizar una lista para generar una lista de fórmula analítica, la función de generación de código que se muestra a continuación es un número impar dentro de una lista de 10

print([i for i in range(10) if i % 2 == 1])

Aquí i for i in range(10)generada Generator es un generador, que puede imprimir, el código siguiente muestra:

print(i for i in range(10))
# 结果
<generator object <genexpr> at 0x000002967560D6D0>

Lista por la fórmula, podemos crear directamente una lista, sin embargo, sujeto a las limitaciones de memoria, la lista es sin duda la capacidad limitada, y crear una lista de 1 millón de elementos incluyen no sólo ocupan mucho espacio de almacenamiento, si sólo se necesita tener acceso a la parte delantera varios elementos, que la gran mayoría del espacio ocupado por los elementos detrás de todo desperdicio.

Por lo tanto, si el elemento de la lista se puede calcular de acuerdo con un algoritmo que si podemos seguir calculando en el ciclo del proceso en una serie de elementos posteriores? Esto elimina la necesidad de crear una lista completa, lo que ahorra mucho espacio, en Python, este tipo 一边循环一边计算de mecanismo, conocido como generador: generador

Constructor es un programa especial, se puede utilizar para controlar el comportamiento del bucle iterativo, Python se genera en 迭代器el uno de los valores de retorno utilizando la función de rendimiento, cada llamada se detiene rendimiento, pero puede usar next()una función y send()generador de recuperación de la función.

生成器类似于返回值为数组的一个函数Esta función puede tomar argumentos, puede ser llamado, sin embargo, diferente de los generales devuelve la función de tiempo uno un conjunto de todos los valores que comprenden, 生成器一次只能产生一个值antes, por lo que la cantidad de memoria consumida se reducirá considerablemente, y se permite que las funciones de llamada rápidamente puede procesar varias valor de retorno, por lo que se ve como un generador de funciones, pero se comporta como un iterador

generador de la creación

Para crear un generador, hay muchas maneras, el primer método es muy simple, sólo la fórmula a una lista de corchetes [] cambiado () paréntesis, crea un generador

alist = [x for x in range(10)]
print(alist)
#生成器
generator_ex = (x for x in range(10))
print(generator_ex)

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
<generator object <genexpr> at 0x0000018B2DBBD660>

¿Cuál es la diferencia entre la lista y luego crear generator_ex es? En la superficie es [] y (), pero el resultado no es el mismo, es una lista impresa (la lista es porque la fórmula), mientras que la segunda impresión es <generador objeto en 0x0000018B2DBBD660>, a continuación, cómo imprimir el generator_ex cada elemento de la misma?

Si desea una copia impresa () función, o por el lado __next __ () devuelve el valor de un generador se obtiene:

generator_ex = (x for x in range(3))
print(next(generator_ex))
print(next(generator_ex))
print(generator_ex.__next__())
# 结果
0
1
2

# 如果调用4次next
print(next(generator_ex))
print(next(generator_ex))
print(generator_ex.__next__())
print(generator_ex.__next__())
# 结果	
StopIteration

Podemos ver, el algoritmo generador se almacena, cada llamada a next (generaotr_ex) para calcular el valor de su siguiente elemento, hasta que el último elemento calculado, cuando no hay más elementos, arrojando StopIterationerrores, y por encima tan constantemente llamando es un mal hábito, el enfoque correcto es utilizar un bucle, porque generator也是可迭代对象:

generator_ex = (x for x in range(3))
for i in generator_ex:
	print(i)
# 结果	
0
1
2

Por ello hemos creado un generador, básicamente, no llame a next (), pero en bucle para iterar a través de, y no se preocupan por error StopIteration generador es muy potente, si el algoritmo extrapolada es complejo, con un tipo similar de generación de la lista tiempo para la circulación no puede ser alcanzado, también se puede implementar como una función.

generador de funciones

Def se define mediante la palabra clave dió una sola vez devuelve un resultado, el bloqueo y empezar de nuevo. Aquí se habla sobre el papel de una función de generador con un número de columna ejemplos fibnacci, el código de la siguiente manera:

#fibonacci数列
def fib(max):
    n,a,b =0,0,1
    while n < max:
        a,b =b,a+b
        n = n+1
        print(a)
    return 'done'
 
a = fib(10)
print(fib(10))

# 上面我们发现,print(b)每次函数运行都要打印,占内存,所以为了不占内存,
# 我们也可以使用生成器,这里叫yield

def fib(max):
    n,a,b =0,0,1
    while n < max:
        yield b
        a,b =b,a+b
        n = n+1
    return 'done'
 
a = fib(10)
print(fib(10))

Dicho aquí sobre el generador de flujo de ejecución y función, la función se ejecuta de forma secuencial, encuentra una instrucción de retorno o instrucción devuelve la última línea de la función. Se convierte en un generador de funciones, se ejecuta cada vez siguiente llamada (), se encuentra con el comando retorna el rendimiento de nuevo el próximo (llamada) desde la última vez que la instrucción de retorno de rendimiento en la urgente necesidad de llevar a cabo, es decir, cuánto, cuánto tomar, no ocupa memoria.

En el caso de un solo subproceso operación de concurrencia por rendimiento

import time
def consumer(name):
    print("%s 准备学习啦!" %name)
    while True:
       lesson = yield
 
       print("开始[%s]了,[%s]老师来讲课了!" %(lesson,name))
 
 
def producer(name):
    c = consumer('A')
    c2 = consumer('B')
    c.__next__()
    c2.__next__()
    print("同学们开始上课 了!")
    for i in range(10):
        time.sleep(1)
        print("到了两个同学!")
        c.send(i) # send的作用是唤醒并继续执行,发送一个信息到生成器内部
        c2.send(i)

Por qué se llama una función de generador? Con el tiempo, ya que genera un valor cola. Función general después de terminado devolverá un valor y salir a continuación, pero 生成器函数会自动挂起,然后重新拾起急需执行que va a usar el rendimiento de palabras clave apagar la función que devuelve un valor a la persona que llama 同时保留了当前的足够多的状态,可以使函数继续执行, generadores e iteradores acuerdos están estrechamente relacionados, que tienen un iterador __next__()miembro método, que devuelve la siguiente iteración de uno de ellos, comprar causa final anormal de una iteración.

Resumir rendimiento:
(1) el habitual para ... ... en el ciclo, en la parte de atrás es una matriz, la matriz es un iterable, hay listas similares, cuerdas, archivos. Él puede ser un = [1,2,3], puede ser un = [x * x para x en el rango de (3)].

Sus desventajas son también evidentes, es decir, todos los datos en el interior de la memoria, si hay grandes cantidades de datos, será muy consumo de memoria.

(2) generador es iterativo, pero puede ser leído sólo una vez. Debido a que sólo se genera cuando se usan, tales como A = (x * x para x en el rango de (3)). Tenga en cuenta que esto es !!! paréntesis en lugar de corchetes.

(3) generador de claves (generador) capaz de iteración es que tiene método next (), el principio es 通过重复调用next()方法,直到捕获一个异常.

(4) Rendimiento ya no funcionan con una función común, pero un generador Generador, iteración puede usarse

(5) el rendimiento es una 类似return 的关键字, rendimiento valor de rendimiento cuando regresó espalda o lado derecho de la primera encuentro iterativo. y下一次迭代的时候,从上一次迭代遇到的yield后面的代码开始执行

(6) el rendimiento es el rendimiento de un valor de retorno, y recordar la posición de retorno. La siguiente iteración se inicia desde esta posición.

(7) con un rendimiento no sólo la función sólo para el bucle, y 可用于某个函数的参数, siempre que los parámetros de esta función permite también un parámetro iterativo.

(8) send()y la next()diferencia es que send可传递参数给yield表达式, esta vez, los parámetros se pasa como el valor de la rendimiento de expresión, y el valor de rendimiento del parámetro se devuelve a la persona que llama, que es send可以强行修改上一个yield表达式值.

(9) send()和next()都有返回值, cuyo valor de retorno se encuentra cuando la iteración actual de rendimiento, rendimiento valores detrás de la expresión, de hecho 当前迭代yield后面的参数.

(10) cuando la primera llamada debe ser el siguiente (), antes de poder enviar (), de lo contrario será error. En la siguiente llamada después de send () antes de que la razón de Nada es porque en ese momento nadie rendimiento, por lo que se puede considerarnext()等同于send(None)

Las expresiones generadoras

Las expresiones generadoras derivan de la combinación de iterativos y listas por comprensión, generadores y similares listas por comprensión, pero utiliza ()en su lugar[ ]

list_comprehension = [x**2 for x in range(10)]
list_generator = (x**2 for x in range(10))

Ya sabemos, por bucle puede actuar directamente sobre los tipos de datos son los siguientes:

  • Una de ellas es 集合数据类型como la lista, tupla, dict, juego, str , etc.
  • Una es generator, que incluye un generador y una función de generador con rendimiento

Estos pueden actuar directamente sobre un objeto contemplado como para iterables bucle Iterable, se puede isinstance()determinar si un objeto es un objeto Iterable

from collections import Iterable

list_comprehension = [x**2 for x in range(10)]
list_generator = (x**2 for x in range(10))
print(isinstance(list_comprehension , Iterable))
print(isinstance(list_generator , Iterable))

True
True

No sólo puede actuar sobre el generador para la circulación, también puede ser el siguiente () la función sigue llamando y devuelve el siguiente valor, hasta el último tiro StopIterationde error dijo que no podía seguir devolviendo el valor siguiente.

try:
	for i in list_generator:
		print(i)
except StopIteration:
	pass

0
1
4
9
16
25
36
49
64
81

iteradorIterator

¿Cuál es el iterador

Una realización iter方法del objeto puede ser iterativa, para lograr un next方proceso de destino es iterativo y es un iterador. Puede ser la próxima () llamada a la función y el retorno al siguiente valor objetivo hace referencia continuamente iterador: Iterator. Por lo que una realización del método y el objetivo siguiente iter método es iterador.

Se puede utilizar el isinstance () determina si un objeto es un objeto iterador.

list_comprehension = [x**2 for x in range(10)]
list_generator = (x**2 for x in range(10))
print(isinstance(list_comprehension, Iterable)) # True
print(isinstance(list_comprehension, Iterator)) # False
print(isinstance(list_generator, Iterable)) 	# True
print(isinstance(list_generator, Iterator)) 	# True

生成器都是Iterator对象Pero list、dict、stra pesar de las Iterable 可迭代对象(), pero 不是Iterator (iteradores).

¿Por qué lista, dict, str y otros tipos de datos no son iterador

Esto es debido a Python Iterator对象表示的是一个数据流, Iterator Los objetos pueden ser la próxima llamada a la función () para volver y seguir los siguientes datos hasta que la ausencia de datos arrojados error StopIteration. Este flujo de datos puede ser visto como una secuencia ordenada, pero no podemos saber de antemano la longitud de la secuencia, sólo puede seguir funcionando para lograr una nueva demanda de computación de datos siguiente (), por lo tanto Iterator的计算是惰性的, sólo los datos que necesita para volver el próximo se calcula.

Iterador incluso pueden representar un flujo infinito de datos, como todos los números naturales. La lista nunca se almacena utilizando todos los números naturales. list、dict、str等数据类型asignación temporal en el momento de la definición de la memoria ha sido asignado, pero iterador es llamar a next ().

! Tenga en cuenta que 文件ambos iterables, sino también iteradores.

from collections import Iterator
from collections import Iterable

f = open('housing.csv')
print(isinstance(f,Iterator)) # True
print(isinstance(f,Iterable)) # True

Esencialmente llamando constantemente al lado () python3 aplicación para la función de bucle, por ejemplo:

for x in [1, 2, 3, 4, 5]:
    pass

################ 实际上完全等价于 ##################

# 首先获得Iterator对象:
it = iter([1, 2, 3, 4, 5])
# 循环:
while True:
    try:
        # 获得下一个值:
        x = next(it)
    except StopIteration:
        # 遇到StopIteration就退出循环
        break

resumen:

  • Para aquellos que pueden actuar en el bucle son Iterable tipo de objeto;
  • Que pueden actuar en la siguiente () Iterator objetos son una función del tipo, que representa una secuencia de evaluación perezosa;
  • La lista de tipos de datos agregados, dict, str, etc., pero es Iterable 不是Iterator, pero puede iter()obtener un objeto funciones iterador.

referencia

  1. https://www.cnblogs.com/wj-1314/p/8490822.html
Publicados 148 artículos originales · ganado elogios 136 · Vistas de 250.000 +

Supongo que te gusta

Origin blog.csdn.net/DlMmU/article/details/105040369
Recomendado
Clasificación