2009-02-01 9 views
7

Que signifie la dernière ligne dans le code suivant?Problème dans la compréhension des compréhensions de la liste Python

import pickle, urllib                                      

    handle = urllib.urlopen("http://www.pythonchallenge.com/pc/def/banner.p") 
    data = pickle.load(handle) 
    handle.close() 

    for elt in data: 
     print "".join([e[1] * e[0] for e in elt]) 

Ma tentative du problème:

  • "" .join ... usages rejoindre -method au texte vide
  • e [1] * e [0] Multiplie deux valeurs suivantes dans la séquence, e
  • Je ne sais pas ce qui est e
  • Je ne sais pas, ce que cela signifie, quand vous avez quelque chose avant de -loop, comme: e[1] * e[0] for e in elt
+0

J'ai vraiment apprécié le défi python quand je l'ai pris il y a quelques années. –

Répondre

19

Peut-être mieux expliqué par un exemple:

print "".join([e[1] * e[0] for e in elt]) 

est la forme abrégée de

x = [] 
for e in elt: 
    x.append(e[1] * e[0]) 
print "".join(x) 

Liste compréhensions sont le sucre simplement syntaxique pour for boucles, qui font une expression sur une séquence d'instructions .

elt peut être un objet arbitraire, puisque vous le chargez à partir de pickles, et e de même. L'utilisation suggère que c'est un type sequence, mais il pourrait s'agir de n'importe quoi qui implémente le protocole de séquence.

+0

Je pense que vous voulez dire "x.append (e [1] * e [0])" .. –

+0

@Marek: John a raison. –

+0

@John: Bien sûr, c'est corrigé. –

4

[e[1] * e[0] for e in elt] est une compréhension de liste, qui évalue une liste elle-même en faisant défiler une autre liste, dans ce cas elt. Chaque élément de la nouvelle liste est e[1]*e[0], où e est l'élément correspondant dans elt.

+0

e peut être un tuple ou dict – SilentGhost

+0

e peut être tout ce qui implémente __getitem__. –

+0

C'est vrai, j'ai fait une mauvaise supposition. –

1

join() est une méthode de chaîne, qui fonctionne sur un séparateur dans la nouvelle chaîne

>>> ':'.join(['ab', 'cd']) 
>>> 'ab:cd' 

et la compréhension de la liste n'est pas là nécessaire, générateur suffirait

7

Tout d'abord, vous avez besoin de mettre http: // devant l'adresse URL, soit: poignée = urllib.urlopen ("http://www.pythonchallenge.com/pc/def/banner.p")

une expression [e pour e en aList] est un list comprehension qui génère une liste de valeurs.

Avec les chaînes Python, l'opérateur * est utilisé pour répéter une chaîne. Essayez de taper dans les commandes un par un dans un interprète puis regardez les données:

>>> data[0] 
[(' ', 95)] 

Cela nous montre chaque ligne de données est un tuple contenant deux éléments.

Ainsi, l'expression e 1 * e [0] est effectivement la chaîne de e [0] répétée e 1 fois. Par conséquent le programme dessine une bannière de

+0

Mais changez les éléments: e [0] = 95 et e [1] = ''. –

+0

merci pour la correction - je suis tellement habitué à faire la chose "sensible" de multiplier une chaîne par un nombre entier que je l'ai lu comme étant ainsi, d'autant plus que c'est ainsi que les données sont stockées! –

1

Andy est une excellente réponse!

Si vous voulez voir toutes les étapes de la boucle (avec sauts de ligne), essayez ceci:

for elt in data: 
    for e in elt: 
     print "e[0] == %s, e[1] == %d, which gives us: '%s'" % (e[0], e[1], ''.join(e[1] * e[0])) 
+0

Il donne une longue liste de: e [0] ==% s, e [1] ==% d –

+0

@Masi: Merci d'avoir remarqué cela. Peut-être que le caractère de saut de ligne ("\") causait des problèmes. Je l'ai supprimé de la réponse. – bernie

2

La question a déjà été pleinement répondu mais je voudrais ajouter que la compréhension de la liste prend également en charge le filtrage. Votre ligne originale

print "".join([e[1] * e[0] for e in elt]) 

pourrait, à titre d'exemple, se

print "".join([e[1] * e[0] for e in elt if len(e) == 2]) 

seulement fonctionner sur les éléments de CLNA qui ont deux éléments.

+0

Digne commentaire! – ChuckCottrill

Questions connexes