Objetos generadores de Python: __sizeof __ ()

Esta puede ser una pregunta estúpida, pero la haré de todos modos. Tengo un objeto generador:

>>> def gen(): ... for i in range(10): ... yield i ... >>> obj=gen() 

Puedo medir su tamaño:

 >>> obj.__sizeof__() 24 

Se dice que los generadores se consumen:

 >>> for i in obj: ... print i ... 0 1 2 3 4 5 6 7 8 9 >>> obj.__sizeof__() 24 

… pero obj.__sizeof__() sigue siendo el mismo.

Con cuerdas funciona como esperaba:

     >>> 'longstring'.__sizeof__() 34 >>> 'str'.__sizeof__() 27 

    Estaría agradecido si alguien me pudiera iluminar.

    __sizeof__() no hace lo que crees que hace. El método devuelve el tamaño interno en bytes para el objeto dado, no la cantidad de elementos que un generador va a devolver.

    Python no puede saber de antemano el tamaño de un generador. Tomemos, por ejemplo, el siguiente generador sin fin (por ejemplo, hay mejores formas de crear un contador):

     def count(): count = 0 while True: yield count count += 1 

    Ese generador es infinito; No hay un tamaño que se le pueda asignar. Sin embargo, el objeto generador en sí toma memoria:

     >>> count.__sizeof__() 88 

    Normalmente no llama a __sizeof__() , deja eso a la función sys.getsizeof() , que también agrega una sobrecarga al recolector de basura.

    Si sabe que un generador será finito y debe saber cuántos artículos devuelve, use:

     sum(1 for item in generator) 

    Pero tenga en cuenta que eso agota el generador.

    Como se dijo en otras respuestas, __sizeof__ devuelve una cosa diferente.

    Solo algunos iteradores tienen métodos que devuelven el número de elementos no devueltos. Por ejemplo, listiterator tiene un método __length_hint__ correspondiente:

     >>> L = [1,2,3,4,5] >>> it = iter(L) >>> it  >>> it.__length_hint__() 5 >>> help(it.__length_hint__) Help on built-in function __length_hint__: __length_hint__(...) Private method returning an estimate of len(list(it)). >>> it.next() 1 >>> it.__length_hint__() 4 

    __sizeof__ devuelve el tamaño de la memoria de un objeto en bytes, no la longitud de un generador, que es imposible de determinar desde el principio, ya que los generadores pueden crecer indefinidamente.

    Si está seguro de que el generador que ha creado es “finito” (tiene un número contable de elementos) y no le importa esperar un momento, puede usar lo siguiente para obtener lo que desea:

     len(list(gen())) 

    Como dicen los otros carteles, __sizeof__() es una medida de la cantidad de memoria que ocupa algo (un concepto de nivel mucho más bajo que probablemente casi nunca necesitarás), no su longitud (que no es una característica de los generadores, ya que no hay garantía de que tengan una longitud contable).

    @Martijn Pieters También puede sobrescribir la función sizeof () y podemos lograr esto que intentamos hacer aquí. Pero no funcionará en algunos tipos de datos como int o float.

     class GetLen(): def __sizeof__(self, x): return len(x) 

    así que aquí para int o float también podemos poner alguna función de escape si el tipo es int o float like.