with - ruptura de rendimiento en Python
what are python generators used for (4)
de acuerdo a la respuesta a esta question , la ruptura de rendimiento en C # es equivalente a la devolución en python. en el caso normal, ''retorno'' de hecho detiene un generador. Pero si su función no hace más que regresar, obtendrá un iterador Ninguno, no vacío, que se devuelve mediante el límite de rendimiento en C #
def generate_nothing():
return
for i in generate_nothing():
print i
obtendrá un TypeError: el objeto ''NoneType'' no es iterable. pero si agrego un rendimiento nunca ejecutado antes del retorno, esta función devuelve lo que espero.
def generate_nothing():
if False: yield None
return
si funciona pero parece cableado ¿Quién tiene una mejor idea?
Gracias,
La parte divertida es que ambas funciones tienen el mismo bytecode. Probablemente hay un indicador que se establece en el generator
cuando el compilador de bytecode encuentra la palabra clave yield
.
>>> def f():
... return
>>> def g():
... if False: yield
#in Python2 you can use 0 instead of False to achieve the same result
>>> from dis import dis
>>> dis(f)
2 0 LOAD_CONST 0 (None)
3 RETURN_VALUE
>>> dis(g)
2 0 LOAD_CONST 0 (None)
3 RETURN_VALUE
Una buena forma de manejar esto es levantar StopIteration que es lo que se StopIteration cuando su iterador no tiene nada más que ceder y se StopIteration a next()
. Esto también saldrá con gracia de un bucle for sin nada dentro del bucle ejecutado.
Por ejemplo, dada una tupla (0, 1, 2, 3)
, quiero obtener pares superpuestos ((0, 1), (1, 2), (2, 3))
. Podría hacerlo así:
def pairs(numbers):
if len(numbers) < 2:
raise StopIteration
for i, number in enumerate(numbers[1:]):
yield numbers[i], number
Ahora los pairs
manejan con seguridad las listas con 1 número o menos.
def generate_nothing():
return
yield
def generate_nothing():
return iter([])