Question

  

Méthodes dict dict.keys (), dict.items ()   et dict.values ??() renvoie & # 8220; views & # 8221;   au lieu de listes.    http://docs.python.org/dev/3.0/whatsnew//3.0 .html

Tout d’abord, en quoi une vue est-elle différente d’un itérateur? Deuxièmement, quel est l'avantage de ce changement? Est-ce juste pour des raisons de performance?

Cela ne me semble pas intuitif, c’est-à-dire que je demande une liste de choses (donnez-moi toutes vos clés) et que je reçois autre chose. Est-ce que cela va dérouter les gens?

Était-ce utile?

La solution

Vous obtenez effectivement une liste. Ce n'est tout simplement pas une copie de la liste interne, mais quelque chose qui agit comme s'il s'agissait d'une liste mais ne représente que l'état interne.

C'est la même chose que dans Java (et probablement dans beaucoup d'autres langages / environnements).

La raison principale en est que, dans de nombreux cas d'utilisation, renvoyer une liste complètement isolée est inutile et inutile. Il faudrait copier tout le contenu (qui peut être peu ou pas).

Si vous souhaitez simplement parcourir les clés, il n'est pas nécessaire de créer une nouvelle liste. Et si vous en avez réellement besoin sous forme de liste séparée (en tant que copie), vous pouvez facilement créer cette liste à partir de la vue.

Autres conseils

La réponse de

Joachim Sauer explique très bien pourquoi une liste n'est pas renvoyée. Mais cela pose la question de savoir pourquoi ces fonctions ne renverraient pas d’itérateurs, comme le font itéritems etc. dans Python 2.

Un itérateur est beaucoup plus restrictif qu'un conteneur. Par exemple, un itérateur n'autorise pas plus d'un passage; si vous essayez une deuxième passe, vous constaterez qu'elle est vide. Par conséquent, les opérations telles que elem in cont sont prises en charge par les conteneurs, mais ne peuvent pas être prises en charge par les itérateurs: une fois que vous avez vérifié si un élément est " in " l'itérateur, l'itérateur est détruit!

D'autre part, obtenir un conteneur requiert généralement une copie, telle que la création d'une liste à partir des clés du dictionnaire.

L'objet view possède le meilleur des deux mondes: il se comporte comme un conteneur et ne copie pas le dictionnaire! En fait, il s’agit d’une sorte de conteneur virtuel en lecture seule qui fonctionne en se liant au dictionnaire sous-jacent. Je ne sais pas si cela se voit ailleurs dans le Python standard.

Modifier:

@AntonyHatchkins: la raison pour laquelle elle ne renvoie pas de fonction de générateur est qu'elle ne permet pas d'opération rapide dans . Oui, dans fonctionne pour les fonctions du générateur (lorsque vous les appelez). C'est-à-dire que vous pouvez faire ceci:

def f():
  for i in range(10):
    yield i

5 in f() # True

Mais selon la définition de dans , si le côté droit est un générateur, python passera par tous les éléments n du générateur - conduisant à O (n) complexité temporelle. Vous ne pouvez rien y faire car c’est le seul comportement significatif d’un générateur arbitraire.

D'autre part, dans le cas de la vue du dictionnaire, vous pouvez implémenter dans à votre guise, car vous en savez plus sur les données que vous gérez. Et en fait, dans est mis en œuvre avec la complexité de O (1) à l'aide d'une table de hachage. Vous pouvez le vérifier en exécutant

>>> d = dict(zip(range(50000000), range(50000000)))
>>> 49999999 in d
True
>>> 49999999 in iter(d) # kinda how generator function would work
True
>>>

et en remarquant à quelle vitesse le premier dans est comparé au deuxième dans .

Comme cela a déjà été mentionné dans la question correspondante, view a la méthode len () , ce qui manque à l'itérateur (la liste en dispose néanmoins).

Un autre avantage de renvoyer une vue au lieu d’une liste est qu’au moins pour les clés, les tests d’appartenance sont optimisés dans les opérations O (1) au lieu de O (N) pour la liste (ou l’itérateur).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top