Je comprends pourquoi la première boucle for fonctionne; cette boucle parcourt essentiellement une liste, selon la méthode readlines().

La seconde for boucle n'a pas de sens pour moi. La boucle ouvre le fichier, mais comme la valeur par défaut d'une instruction open est lue , la sortie ne devrait-elle pas être le fichier entier dans une grande chaîne à chaque itération, au lieu d'une seule ligne?

Voici le code:

#The two for loops do the same thing:

for line in open('test.txt').readlines():
    print(line.rstrip())
for line in open('test.txt'): # Use iterators: best for text input
    print(line.rstrip())
0
Jeff - Mci 12 avril 2018 à 11:53

3 réponses

Meilleure réponse

Vous avez mal compris le «défaut» ici. La valeur par défaut que vous avez trouvée parle du mode fichier ; la valeur par défaut est d'ouvrir le fichier pour la lecture. Le fichier ne sera pas lu à ce stade, il indique au système d'exploitation que vous souhaitez accéder à un fichier qui doit déjà exister et est lisible par votre processus.

open() renvoie toujours un objet fichier. Et les objets fichier sont itérables, vous pouvez donc en parcourir un, à condition qu'il soit ouvert pour la lecture (le mode est donc 'r', ou 'w+' ou 'a+').

Dans la open() documentation:

Ouvrez le fichier et renvoyez un objet fichier .

Et

mode est une chaîne facultative qui spécifie le mode dans lequel le fichier est ouvert. Il est par défaut 'r', ce qui signifie ouvert pour la lecture en mode texte. Les autres valeurs courantes sont 'w' pour l'écriture (tronquer le fichier s'il existe déjà), 'x' pour la création exclusive et 'a' pour ajouter [.]

open() renvoie toujours un objet qui hérite de {{X1} }, et il dit ceci à propos de l'itération:

IOBase (et ses sous-classes) prend en charge le protocole itérateur, ce qui signifie qu'un objet IOBase peut être itéré au-dessus du rendement des lignes dans un flux. Les lignes sont définies légèrement différemment selon que le flux est un flux binaire (donnant des octets) ou un flux de texte (donnant des chaînes de caractères).

Vous devez toujours utiliser l'itération sur le fichier sur l'itération sur .readlines(); ce dernier lit toutes les lignes en mémoire en une seule étape, place toutes ces lignes dans une liste, puis renvoie cette liste. Cela causera certainement des problèmes lorsque le fichier que vous avez ouvert est volumineux. Si tout ce dont vous avez besoin est d'accéder aux lignes individuelles, une par une, l'itération sur le fichier lui-même ne créera des lignes que si nécessaire, et la mise en mémoire tampon se charge de rendre cela efficace (le système d'exploitation est invité à fournir des données en morceaux pratiques pour le traitement de Python en lignes).

Notez que même si open() a renvoyé une seule chaîne contenant tout le contenu du fichier, l'itération aurait alors lieu sur une séquence de caractères; vous ne verriez pas le contenu du fichier répété. Vous pouvez essayer cela avec la commande file.read():

>>> with open('/tmp/demo.txt', 'w') as outputfile:  # opened for writing
...     outputfile.write(  # write 3 lines
...         'Neque porro quisquam\n'
...         'est qui dolorem ipsum\n'
...         'quia dolor sit amet\n')
...
63
>>> for i, value in enumerate(open('/tmp/demo.txt').read()):  # read everything into a string
...     if i > 5:  # limit the output, enumerate provided us with an index
...         break
...     print(value)
...
N
e
q
u
e

Une autre raison pour laquelle les données du fichier ne se répéteraient pas est que les fichiers ressemblent beaucoup à la bande magnétique classique: les fichiers ont une position de fichier , qui avance le long du fichier lorsque vous lisez des données, et cette position ne revient pas automatiquement au début une fois que vous avez atteint la fin. Sans rouvrir un fichier, ni utiliser la méthode file.seek() pour redéfinir la position du fichier, vous ne pouvez lire les données qu'une seule fois :

>>> with open('/tmp/demo.txt') as inputfile:
...     print(len(inputfile.read()))  # get all data, and print the length
...     print(len(inputfile.read()))  # try again, note that we got no data this time!
...     __ = inputfile.seek(0)   # rewind to the start
...     print(len(inputfile.read()))  # try again, now we get data again
...
63
0
63
3
Martijn Pieters 12 avril 2018 à 09:18

Une boucle

for i in iterable: 
    # some code with i

Est fondamentalement un raccourci pour

iterator = iter(iterable)
while True:
    try:
        i = next(iterator)            
    except StopIteration:
        break
    # some code with i

Ainsi, la boucle for extrait les valeurs d'un itérateur construit à partir de l'itérable un par un et reconnaît automatiquement quand cet itérateur est épuisé et s'arrête.

Il se trouve que la valeur de retour de open est un itérateur qui vous donne une ligne pour chaque appel à sa méthode __next__.

Prime:

Dans votre cas, open('test.txt') renvoie un itérateur, donc appeler __iter__ dessus renvoie l'itérateur lui-même.

>>> it = open('test.txt')
>>> iter(it) is it
True
0
timgeb 12 avril 2018 à 09:00

Consultez la documentation de python: https://docs.python.org/3/library/functions.html# ouvrir

Le mode par défaut est 'r' (ouvert pour la lecture de texte, synonyme de 'rt'). Pour l'accès en lecture-écriture binaire, le mode «w + b» s'ouvre et tronque le fichier à 0 octet. 'r + b' ouvre le fichier sans troncature.

Comme mentionné dans la vue d'ensemble, Python fait la distinction entre les E / S binaires et texte. Les fichiers ouverts en mode binaire (y compris «b» dans l'argument mode) renvoient le contenu sous forme d'octets sans aucun décodage. En mode texte (par défaut, ou lorsque `` t '' est inclus dans l'argument mode), le contenu du fichier est retourné sous forme de str, les octets ayant d'abord été décodés à l'aide d'un codage dépendant de la plate-forme ou à l'aide du codage spécifié s'il est fourni.

C'est à cause du réglage par défaut de la fonction open()

0
shep4rd 12 avril 2018 à 09:01