J'aime l'idée de la fonction de générateur @ iWerner. Un petit changement à son code et il fait ce que la question a demandé.
def readlines(filename):
f = open(filename)
# discard first lines that start with '#'
for line in f:
if not line.lstrip().startswith("#"):
break
yield line
for line in f:
yield line
et de l'utiliser comme
for line in readlines("data.txt"):
# do things
pass
Mais voici une approche différente. C'est presque très simple. L'idée est que nous ouvrons le fichier et obtenons un objet fichier, que nous pouvons utiliser comme un itérateur. Ensuite, nous tirons les lignes que nous ne voulons pas de l'itérateur, et retournons simplement l'itérateur. Ce serait idéal si nous savions toujours combien de lignes sauter. Le problème ici est que nous ne savons pas combien de lignes nous devons sauter; nous avons juste besoin de tirer les lignes et de les regarder. Et il n'y a aucun moyen de remettre une ligne dans l'itérateur, une fois que nous l'avons tiré. Donc: ouvrir l'itérateur, tirer les lignes et compter combien de ont le caractère '#' en tête; puis utilisez la méthode .seek()
pour rembobiner le fichier, tirez à nouveau le bon numéro et renvoyez l'itérateur. Une chose que j'aime à ce sujet: vous récupérez l'objet fichier réel, avec toutes ses méthodes; vous pouvez simplement utiliser ceci au lieu de open()
et cela fonctionnera dans tous les cas. J'ai renommé la fonction à open_my_text()
pour refléter cela.
def open_my_text(filename):
f = open(filename, "rt")
# count number of lines that start with '#'
count = 0
for line in f:
if not line.lstrip().startswith("#"):
break
count += 1
# rewind file, and discard lines counted above
f.seek(0)
for _ in range(count):
f.readline()
# return file object with comment lines pre-skipped
return f
Au lieu de f.readline()
je aurais pu utiliser f.next()
(pour Python 2.x) ou next(f)
(pour Python 3.x) mais je voulais écrire il était portable à tout Python.
EDIT: D'accord, je sais que personne ne se soucie et je "ne reçois aucun upvotes pour cela, mais je l'ai re-écrit ma réponse une dernière fois pour le rendre plus élégant
Vous ne pouvez pas mettre un. retournez dans un itérateur, mais vous pouvez ouvrir un fichier deux fois et obtenir deux itérateurs, étant donné la façon dont fonctionne la mise en cache des fichiers, le deuxième itérateur est presque libre. , cette version serait grandement surperformer la version précédente qui appelle f.seek(0)
.
def open_my_text(filename):
# open the same file twice to get two file objects
# (We are opening the file read-only so this is safe.)
ftemp = open(filename, "rt")
f = open(filename, "rt")
# use ftemp to look at lines, then discard from f
for line in ftemp:
if not line.lstrip().startswith("#"):
break
f.readline()
# return file object with comment lines pre-skipped
return f
cette version est beaucoup mieux que la version précédente, et encore des retours un objet fichier complet avec toutes ses méthodes.
http://stackoverflow.com/questions/1706198/python-how-to-ignore-comment-lines-when-reading-in-a-file/1706204#1706204 – ghostdog74
"Shorter" n'est pas nécessairement "Pythonic" . Ce que vous avez est très net, clair et évident. Le fait de l'écraser dans un doublage obscur ne favorise pas toujours la Pythonicité. Tout comme j'aime les outils, parfois son approche fonctionnelle me fait arrêter de me gratter la tête. Le code Pythonic devrait nécessiter peu ou pas de grattage de la tête. Si je devais voter pour une forme alternative et l'appeler plus Pythonic, ce serait la solution de compréhension de liste de Jim Dennis. – PaulMcG