2009-03-31 13 views
2

De nombreuses méthodes utilisées pour retourner les listes en Python 2.x semblent maintenant revenir itérateurs dans Py3KPy3K conservation de la mémoire en retournant itérateurs plutôt que des listes

Sont également itérateurs générateur d'expressions? Évaluation paresseuse?

Ainsi, avec cela, l'empreinte mémoire de python va se réduire drastiquement. N'est-ce pas?

Qu'en est-il des programmes convertis de 2to3 en utilisant le script intégré? L'outil intégré convertit-il explicitement tous les itérateurs retournés en listes, pour des raisons de compatibilité? Si c'est le cas, l'avantage de l'empreinte mémoire de Py3k n'est pas vraiment apparent dans les programmes convertis. Est-ce?

Répondre

7

Beaucoup d'entre eux ne sont pas exactement des itérateurs, mais des objets de vue spéciaux. Par exemple, range() renvoie maintenant quelque chose de similaire à l'ancien objet xrange - il peut toujours être indexé, mais construit paresseusement les entiers selon les besoins.

De même dict.keys() donne un objet dict_keys implémentant une vue sur le dict, plutôt que de créer une nouvelle liste avec une copie des clés.

Comment cela affecte les empreintes de mémoire dépend probablement du programme. Il y a certainement plus d'emphase sur l'utilisation des itérateurs, sauf si vous avez vraiment besoin de listes, alors que l'utilisation de listes était généralement le cas par défaut dans python2. Cela entraînera probablement un programme plus efficace en termes de mémoire. Les cas où il y a vraiment de grosses économies vont probablement être implémentés comme itérateurs dans les programmes python2, étant donné que l'utilisation de la mémoire est très importante et est plus susceptible d'être déjà adressée. (par exemple, l'itérateur de fichier est déjà beaucoup plus efficace en mémoire que l'ancienne méthode file.readlines())

La conversion est effectuée par l'outil 2to3, et convertit généralement des éléments tels que range() en itérateurs où il peut déterminer en toute sécurité une liste réelle. « t nécessaire, donc le code comme:

for x in range(10): print x 

passera au nouvel objet gamme(), sans créer plus d'une liste, et ainsi obtiendra la prestation de mémoire réduite, mais le code comme:

x = range(20) 

sera converti en:

x = list(range(20)) 

que le convertisseur ne peut pas savoir si le code prévoit un objet réel de la liste dans x.

1

Les itérateurs sont-ils aussi des expressions de générateur? Évaluation paresseuse?

Un itérateur est juste un objet avec une méthode suivante. Ce que la documentation signifie la plupart du temps en disant qu'une fonction retourne un itérateur, c'est que son résultat est paresseusement chargé.

Ainsi, avec cela, l'empreinte mémoire de python va considérablement diminuer. N'est-ce pas?

Cela dépend. Je devinerais que le programme moyen ne remarquerait pas une différence énorme cependant.Les avantages de performance des itérateurs sur les listes ne sont vraiment importants que si vous avez un grand ensemble de données. Vous pouvez voir this question.

0

L'un des plus grands avantages des itérateurs sur les listes n'est pas la mémoire, mais bien le temps de calcul. Par exemple, en Python 2:

for i in range(1000000): # spend a bunch of time making a big list 
    if i == 0: 
     break # Building the list was a waste since we only looped once 

Maintenant prenez par exemple:

for i in xrange(1000000): # starts loop almost immediately 
    if i == 0: 
     break # we did't waste time even if we break early 

Bien que l'exemple est contraint, le cas d'utilisation ne sont pas: les boucles sont souvent brisées de mi-chemin. Construire une liste entière pour n'en utiliser qu'une partie est un gâchis à moins que vous ne l'utilisiez plus d'une fois. Si c'est le cas, vous pouvez explicitement construire une liste: r = list(range(100)). C'est pourquoi les itérateurs sont la valeur par défaut dans plus d'endroits dans Python 3; Vous n'avez rien à dire puisque vous pouvez toujours créer explicitement des listes (ou d'autres conteneurs) quand vous en avez besoin. Mais vous n'êtes pas obligé de le faire lorsque tout ce que vous avez l'intention de faire est de parcourir une fois une itérative (ce que je dirais est le cas le plus fréquent).