2017-10-18 12 views
0

J'ai trouvé un script Python appelé transpose_file.py qui peut transposer des fichiers délimités par des espaces. Il ressemble donc:Comprendre le script de transposition python

import fileinput 

m = [] 
for line in fileinput.input(): 
    m.append(line.strip().split(" ")) 
for row in zip(*m): 
    print " ".join(row) 

Je veux vous assurer que je comprends ce que chaque ligne fait, comme je suis très nouveau pour Python.

1) D'abord, nous importons un module appelé fileinput qui vous permet de lire les fichiers et de les analyser. Je ne sais pas pourquoi l'aide d'un simple ouvert (sys.argv [1], 'r') que f etc ne fonctionnerait pas

2) Faire une liste vide appelée m

3) Pour chaque ligne de votre entrée fichier, dépouiller tout espace, tabulation ou nouvelle ligne à la fin de la ligne, et faire de l'espace le délimiteur (ie votre fichier d'entrée est délimité)

4) Pour chaque ligne ... pas sûr de ce que le reste signifie. Que signifie zip (* m)? Une fois cela fait, nous imprimons un espace et nous rejoignons la rangée? Je ne vois tout simplement pas comment cela se traduit par une transposition.

Toute explication serait grandement appréciée.

Répondre

1
  1. fileinput soutient d'autres méthodes d'entrée de fichier ainsi. Il peut effectivement faire open(sys.argv[1],'r'), mais prend également en charge d'autres possibilités - voir le Python documentation pour cela.

  2. Votre compréhension de 2 et 3 est largement correct

  3. Pour chaque ligne, la ligne est dépouillée d'espaces, puis divisé par des espaces. Cela entraîne une grille représentant chaque partie du fichier délimitée par des espaces.

  4. zip(*) est effectivement l'opérateur de transposition de Python. Par exemple:

    In [1]: data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 
    
    In [2]: data 
    Out[2]: [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 
    
    In [3]: transp = list(zip(*data)) 
    
    In [4]: transp 
    Out[4]: [(1, 4, 7), (2, 5, 8), (3, 6, 9)] 
    

    Vous devez contraindre à un list comme zip renvoie un itératives. zip est peut-être plus souvent utilisé pour « zip » ensemble deux listes, vous pouvez parcourir les ensemble:

    In [1]: list(zip(["one", "three", "five"], ["two", "four", "six"])) 
    Out[1]: [('one', 'two'), ('three', 'four'), ('five', 'six')] 
    

    C'est aussi bien documented.

    L'opérateur * sépare chaque sous-liste de la grille en un argument distinct à zip.

    " ".join ensemble chaque chaîne rejoint dans un itérables avec un espace - par exemple

    In [1]: " ".join(["foo", "bar", "baz"]) 
    Out[1]: 'foo bar baz' 
    

    Cela met juste l'espace délimiteurs de nouveau dans votre série de chaînes nouvellement transposées. C'est à nouveau, documented.

1

Votre analyse est fondamentalement correcte.

Notez que

line.strip().split(" ") 

est un peu fragile. Il supprime tous les espaces de fin de la ligne, puis divise la ligne en une liste de chaînes, en utilisant un seul espace comme délimiteur. Cela peut ne pas faire ce que vous voulez si la ligne contient des exécutions de plus d'un espace, ou si elle contient des onglets.


Les itère de fonction zip sur ses arguments en parallèle, la construction des tuples dans chaque arg éléments correspondants. Alors d'abord, il génère un tuple de tous les premiers éléments, puis tous les seconds éléments, etc.

Par exemple:

for t in zip([1, 2, 3], [4, 5, 6], [7, 8, 9]): 
    print(t) 
print() 

sortie

(1, 4, 7) 
(2, 5, 8) 
(3, 6, 9) 

Comme vous pouvez le voir, ce résultat dans une transposition.

Nous pouvons utiliser l'opérateur * « Splat » pour passer une liste de séquences à zip, l'opérateur « Splat » dépaquète la liste afin que zip voit chacune de ces séquences en tant que arg séparée.

lst = [ 
    [1, 2, 3], 
    [4, 5, 6], 
    [7, 8, 9], 
] 

for t in zip(*lst): 
    print(t) 

Ceci donne la même sortie qu'avant.

L'opérateur "splat" n'est pas seulement une caractéristique spéciale de zip: vous pouvez l'utiliser sur n'importe quelle fonction qui prend plusieurs arguments. Il y a aussi l'opérateur "double-splat" **, qui décompresse les dictionnaires en paires mot-clé = valeur.

Si les séquences diffèrent en longueur, zip s'arrête lorsqu'il n'y a plus d'éléments dans la séquence la plus courte.Cependant, il existe une fonction connexe dans le module itertools standard: itertools.zip_longest, qui prend un fillvalue en option. Il continue jusqu'à ce que la plus longue séquence soit épuisée, en utilisant fillvalue pour combler les lacunes. La valeur par défaut fillvalue est None.


En ce qui concerne fileinput, certaines personnes trouvent juste pratique, je préfère with open( ...