Dlaczego nie mogę użyć ciągu znaków dla nowej linii w funkcji write (), ale mogę go użyć w writelines ()?
Pomysł jest następujący: jeśli chcesz napisać pojedynczy ciąg, możesz to zrobić za pomocą write()
. Jeśli masz sekwencję ciągów, możesz je wszystkie zapisać za pomocą writelines()
.
write(arg)
oczekuje łańcucha jako argumentu i zapisuje go do pliku. Jeśli podasz listę ciągów, zgłosi to wyjątek (przy okazji pokaż nam błędy!).
writelines(arg)
oczekuje iterowalnego argumentu (obiekt iterowalny może być krotką, listą, łańcuchem lub iteratorem w najbardziej ogólnym sensie). Każdy element zawarty w iteratorze powinien być ciągiem. Podałeś krotkę ciągów, więc wszystko zadziałało.
Natura ciągu (ów) nie ma znaczenia dla obu funkcji, tzn. Po prostu zapisują do pliku wszystko, co im podasz. Ciekawe jest to, żewritelines()
nie dodaje samodzielnie znaków nowej linii, więc nazwa metody może być dość myląca. W rzeczywistości zachowuje się jak wyimaginowana metoda o nazwie write_all_of_these_strings(sequence)
.
Poniżej przedstawiono idiomatyczny sposób w Pythonie, aby zapisać listę ciągów do pliku, zachowując każdy ciąg w osobnym wierszu:
lines = ['line1', 'line2']
with open('filename.txt', 'w') as f:
f.write('\n'.join(lines))
To zajmie się zamknięciem pliku za Ciebie. Konstrukcja'\n'.join(lines)
konkatenuje (łączy) ciągi znaków z listy lines
i używa znaku „\ n” jako kleju. Jest to bardziej wydajne niż korzystanie z +
operatora.
Zaczynając od tej samej lines
sekwencji, kończąc na tym samym wyjściu, ale używając writelines()
:
lines = ['line1', 'line2']
with open('filename.txt', 'w') as f:
f.writelines("%s\n" % l for l in lines)
Wykorzystuje to wyrażenie generatora i dynamicznie tworzy ciągi zakończone znakiem nowej linii. writelines()
iteruje po tej sekwencji ciągów i zapisuje każdy element.
Edycja: Kolejna kwestia, o której powinieneś wiedzieć:
write()
i readlines()
istniał przed writelines()
wprowadzeniem. writelines()
został wprowadzony później jako odpowiednik readlines()
, dzięki czemu można było łatwo napisać treść pliku, który został właśnie odczytany przez readlines()
:
outfile.writelines(infile.readlines())
Naprawdę, to jest główny powód, dla którego writelines
ma tak mylącą nazwę. Dzisiaj nie chcemy już używać tej metody. readlines()
czyta cały plik do pamięci twojego komputera przed writelines()
rozpoczęciem zapisywania danych. Przede wszystkim może to tracić czas. Dlaczego nie zacząć zapisywać części danych podczas czytania innych części? Ale co najważniejsze, takie podejście może pochłaniać dużo pamięci. W skrajnym scenariuszu, w którym plik wejściowy jest większy niż pamięć komputera, takie podejście nawet nie zadziała. Rozwiązaniem tego problemu jest użycie tylko iteratorów. Działający przykład:
with open('inputfile') as infile:
with open('outputfile') as outfile:
for line in infile:
outfile.write(line)
To czyta plik wejściowy wiersz po wierszu. Gdy tylko zostanie odczytana jedna linia, ta linia jest zapisywana do pliku wyjściowego. Mówiąc schematycznie, zawsze jest tylko jedna linia w pamięci (w porównaniu do całej zawartości pliku znajdującej się w pamięci w przypadku podejścia readlines / writelines).
lines
w twoim przykładzie nie jest ciągiem. Jest to krotka składająca się z sześciu strun.