¿Qué significa “consumir” en Python? ¿En un iterador?

He estado trabajando en Python durante algunos meses, y se me ha ocurrido que a menudo me olvido del vocabulario que se me escapa a primera vista, en lugar de tratar de obtener una idea general. Ahora, mirando hacia atrás, todavía me encuentro confundido, más allá de lo que se cree, a lo que se refiere el término consumir . Mi interés inicial provino de las explicaciones de los iteradores que hablaban del valor del consumo de un iterador. Sin embargo, mirando a su alrededor, esto no parece ser un lugar común en el léxico de Python. ¿O es eso? Al buscar aquí, se encuentran principalmente referencias a servicios web y una o dos discusiones sobre cómo ocultar esto o el resultado de una función.

Supongo entonces, para romper mi ignorancia en unos pocos puntos de base:

  1. ¿El “consumo” hace cosas diferentes en diferentes contextos pythonicos?
  2. ¿Qué sucede con los datos cuando se consumen, como en iter() ?
  3. Cuando se asigna una variable al resultado de un iterador, el dato supuestamente consumido, ¿ya no pertenece al iterador?
  4. ¿Puede consumir más de un valor de un objeto iterador en una sola llamada al iterador?

Espero que tenga algún tipo de sentido. Tenga en cuenta que esto no se refiere a ninguna necesidad particular; Simplemente estoy confundido más allá de la plausibilidad racional.

EDITAR: Una cosa más … ¿un valor iterado (cuando se llama con next() ) permanece en la memoria?

Respecto de 2.

De hecho, hay que distinguir dos casos.

Recuerda lo que Greg Hewgill escribió:

Un “iterador” es un objeto único que es responsable de crear una secuencia de elementos. Esta secuencia puede ser elementos de una lista existente, o puede ser algo calculado, como los números primos o los dígitos decimales de π.

Primer caso :

el iterador calcula el objeto que debe producir cuando se estimula; es decir, el objeto producido no existía antes de la llamada de next() . En consecuencia, si se asigna un nombre al objeto, este último sobrevivirá; si no, el objeto existirá sin estar vinculado a un nombre en un espacio de nombres durante un tiempo determinado, y luego desaparecerá de la memoria, es decir, los bits que ocupa se usarán para otro objeto más tarde o más temprano.

El segundo caso

es cuando el iterador retorna objetos existentes que pertenecen a una lista, una tupla, un diccionario, etc. En este caso, cada objeto producido por next() ya tenía un enlace con un nombre. Luego, si el objeto se asigna a un nuevo nombre cuando “sale” del iterador, habrá dos nombres vinculados al objeto. Y si el objeto no está asignado a un nombre, seguirá vinculado a un solo nombre, lo que es suficiente para mantener el objeto vivo.

En común:

Cada vez que se produce un objeto mediante una llamada de un iterador, si no se le asigna ningún nombre, el único resultado de la operación es que el iterador se ha “consumido”. Es una manera de decir que incluso si no hay una consecuencia permanente después de la producción de un objeto, ha ocurrido algo que deja un rastro dentro del iterador.

Uno habla de consumir el iterador cuando se asigna un nombre al objeto, sin embargo, no quiero confundir.

Nota:

De hecho, en el caso de un objeto preexistente en una lista, digamos, puede ser que no tenga nombre. Pero la lista contiene una referencia de cada objeto que “contiene” … De hecho, una lista no “contiene” objetos, sino solo referencias a objetos … Bueno, eso va más allá de lo que quería decir.

.

Respecto a 3

No debes escribir 3: “Cuando una variable se asigna a …”

La palabra variable es un escollo en Python porque tiene un significado ambiguo. No hay variables en Python, en el sentido común conocido en otros idiomas, es decir, una «porción delimitada de la memoria cuyo valor puede cambiar». Solo hay objetos. La palabra variable se usa habitualmente para significar un identificador . Por lo tanto, es una mejor práctica llamarlo identificador o nombre . Esto evita la confusión.

.

Respecto a 4

No creo que sea posible obtener dos retornos del iterador con solo una llamada next()

El término “consumir” es un término informal que se refiere a la forma en que los iteradores trabajan en Python. Un “iterador” es un objeto único que es responsable de crear una secuencia de elementos. Esta secuencia puede ser elementos de una lista existente, o puede ser algo calculado, como los números primos o los dígitos decimales de π.

Cuando una persona que llama solicita el elemento “siguiente” a un iterador, el iterador proporciona el siguiente elemento y luego cambia su propio estado para que esté listo para producir el siguiente elemento después de eso. Esto usualmente es lo que esperas.

Si tengo un generador que produce la secuencia de números primos crecientes, la primera vez que lo llame obtendré 2 a cambio. La próxima vez, obtendré 3. Si luego te doy una referencia a ese generador, lo llamarás (por lo que crees que es la primera vez) y obtendré 5. No hay manera de “reiniciar” el generador para que comience nuevamente en 2, excepto al crear una instancia completamente nueva del generador. En esa situación, podría decir que ya he consumido los dos primeros artículos antes de entregarle el generador.

No soy un experto en Python, pero puedo decir esto: la mayor parte del tiempo, el consumo en la progtwigción es lo contrario de la producción. Puedes clasificar algunos procesos como productores, que crean valores; y otros como consumidores, que utilizan los valores creados por los productores.

En el caso de un iterador, un iterador es un productor que pasa por un objeto iterable y “produce” cada valor, uno a la vez, en orden. “Consumir” datos de un iterador simplemente significa usarlos.

Los iteradores son solo objetos que admiten los métodos __iter__ y next . El caso de uso general de los iteradores es hacer un bucle sobre ellos, donde cada vez que se recorre el bucle, el resultado de iterator.next() se asignará a una variable.

Teniendo esto en cuenta, una llamada a iterator.next() podría denominarse “consumir un valor” porque, en general, una llamada a next cambia el estado del iterador, y no hay forma de volver a ese estado anterior.

Sin embargo, no hay nada que impida que un iterador devuelva el mismo valor repetidamente, o incluso que proporcione una manera de regresar a un estado anterior. En esos casos, el uso de la palabra “consumir” puede no ser tan aplicable.

En cuanto a lo que sucede con los datos que devuelve el next método del iterador, depende completamente de la implementación del iterador. Los generadores tienden a descartar los resultados que producen, pero si un contenedor también es un iterador, los datos devueltos cuando se llama a next() seguirán existiendo en el objeto contenedor.

Puedo responder tu primer punto, consumir es agotar un iterable, esto significa ejecutar el iterable de los siguientes elementos.

¿El “consumo” hace cosas diferentes en diferentes contextos pythonicos?

No, “consumir” siempre hace lo mismo.

¿Qué sucede con los datos cuando se consumen, como en iter ()?

Ya no está disponible desde el lugar donde lo obtuviste.

Cuando se asigna una variable al resultado de un iterador, el dato supuestamente consumido, ¿ya no pertenece al iterador?

Correcto. Tan pronto como el iterador produce los datos, los datos ya no pertenecen al iterador.

¿Puede consumir más de un valor de un objeto iterador en una sola llamada al iterador?

Por lo general, no. Sin embargo, puede escribir un iterador personalizado que produzca más de uno de sus valores a la vez.