Wiele sposobów formatowania napisów w Pythonie - czy starsze (będą) przestarzałe?

106

Python ma co najmniej sześć sposobów formatowania łańcucha:

In [1]: world = "Earth"

# method 1a
In [2]: "Hello, %s" % world
Out[2]: 'Hello, Earth'

# method 1b
In [3]: "Hello, %(planet)s" % {"planet": world}
Out[3]: 'Hello, Earth'

# method 2a
In [4]: "Hello, {0}".format(world)
Out[4]: 'Hello, Earth'

# method 2b
In [5]: "Hello, {planet}".format(planet=world)
Out[5]: 'Hello, Earth'

# method 2c
In [6]: f"Hello, {world}"
Out[6]: 'Hello, Earth'

In [7]: from string import Template

# method 3
In [8]: Template("Hello, $planet").substitute(planet=world)
Out[8]: 'Hello, Earth'

Krótka historia różnych metod:

  • printfformatowanie w stylu istnieje od czasów dzieciństwa Pythona
  • TemplateKlasy wprowadzono 2,4 Python
  • formatMetodę wprowadzono 2,6 Python
  • f-strings zostały wprowadzone w Pythonie 3.6

Moje pytania to:

  • Czy printfformatowanie w stylu jest przestarzałe, czy też zostanie wycofane?
  • W Template class, czy substitutemetoda jest przestarzała, czy będzie przestarzała? (Nie mówię o tym safe_substitute, co, jak rozumiem, oferuje unikalne możliwości)

Podobne pytania i dlaczego uważam, że nie są duplikatami:

Zobacz też

gerrit
źródło
1
Czy muszę zaznaczyć, że zapomniałeś o Formatterzajęciach?
Martijn Pieters

Odpowiedzi:

14

Chociaż w dokumentach istnieją różne wskazania, że .formati f-stringi są lepsze od %stringów, nie ma istniejącego planu, aby kiedykolwiek zdezaktualizować to drugie.

W zatwierdzeniu Wydanie nr 14123: Wyraźnie wspomnij, że formatowanie ciągu znaków% w starym stylu ma zastrzeżenia, ale nie zniknie w najbliższym czasie. zainspirowany numerem Wskazuje, że obecnie nie ma planów wycofania formatowania w stylu printf , dokumenty w%-formatowaniu zostały zmodyfikowane tak, aby zawierały następującą frazę:

Ponieważ nowa składnia formatowania ciągów jest bardziej elastyczna i naturalnie obsługuje krotki i słowniki, jest ona zalecana w przypadku nowego kodu. Jednak, obecnie nie ma planów wycofania formatowania w stylu printf .

(Podkreśl moje.)

Fraza ta została później usunięta w zatwierdzeniu Zamknij # 4966: przebuduj dokumentację sekwencji, aby lepiej wyjaśnić stan współczesnego Pythona . Może się to wydawać oznaką, że plan wycofania %formatowania powrócił na karty ... ale zanurzenie się w narzędziu do śledzenia błędów ujawnia, że ​​intencja była odwrotna. W narzędziu do śledzenia błędów autor zatwierdzenia charakteryzuje zmianę w następujący sposób :

  • zmienił prozę opisującą związek między formatowaniem w stylu printf a metodą str.format (celowo usuwając sugestię, że ta pierwsza stanowi jakiekolwiek realne niebezpieczeństwo zniknięcia - po prostu nie jest praktyczne, abyśmy poważnie myśleli o jej zabiciu)

Innymi słowy, wprowadziliśmy dwie kolejne zmiany w %dokumentach -formatting, które mają wyraźnie podkreślić , że nie być przestarzała, nie mówiąc już usunięte. Dokumenty pozostają uparte co do względnych zalet różnych rodzajów formatowania ciągów, ale są również jasne, że %-formatowanie nie zostanie wycofane ani usunięte.

Co więcej, plik ostatnia zmiana tego akapitu w marcu 2017 r. Zmieniła go z tego ...

Opisane tutaj operacje formatowania wykazują różne dziwactwa, które prowadzą do wielu typowych błędów (takich jak nieprawidłowe wyświetlanie krotek i słowników). Używanie nowszych sformatowanych literałów ciągów lub str.formatinterfejsu pomaga uniknąć tych błędów. Te alternatywy zapewniają również bardziej wydajne, elastyczne i rozszerzalne podejście do formatowania tekstu.

... do tego:

Opisane tutaj operacje formatowania wykazują różne dziwactwa, które prowadzą do wielu typowych błędów (takich jak nieprawidłowe wyświetlanie krotek i słowników). Użycie nowszych sformatowanych literałów ciągów, str.formatinterfejsu lub ciągów szablonów może pomóc uniknąć tych błędów. Każda z tych alternatyw zapewnia własne kompromisy i korzyści w postaci prostoty, elastyczności i / lub rozszerzalności.

Zwróć uwagę, że zmiana z „pomaga unikać” na „może pomóc uniknąć” oraz jak wyraźne zalecenia .formati f-strings zostały zastąpione puszystą, dwuznaczną prozą o tym, jak każdy styl „zapewnia własne kompromisy i korzyści” . Oznacza to, że nie tylko formalne wycofanie nie jest już na kartach, ale obecni dokumentatorzy otwarcie przyznają, że %formatowanie ma przynajmniej pewne „zalety” w stosunku do innych podejść.

Wnioskowałbym z tego wszystkiego, że ruch mający na celu wycofanie lub usunięcie %formatowania nie tylko zawahał się, ale został całkowicie i trwale pokonany.

Mark Amery
źródło
2
Puszysta zmiana języka została dodana, aby uspokoić opiekunów Mercuriala (między innymi), którzy nie chcieli widzieć Mercuriala pozostawionego z zbyt dużym kodem, aby wyeliminować jego użycie %. Teraz, gdy polityka „zakazu modyfikowania kodu na dużą skalę” została odrzucona, ich zastrzeżenia również znikają. Na dłuższą metę utrzymanie obu formularzy bez żadnych korzyści % w pewnym momencie i tak zostanie usunięta. Po prostu nie wiemy jeszcze kiedy, więc warto było stonować język.
Martijn Pieters
@MartijnPieters Ciekawe. Wygląda na to, że masz ogromną wiedzę na temat tej decyzji, której mi brakuje. Jeśli chodzi o to, co jest warte, myślę, że dobrze przywołana odpowiedź od Ciebie, przedstawiająca te punkty (jako nowa odpowiedź lub zmiana istniejącej) miałaby wartość.
Mark Amery,
58

Nowa .format()metoda ma zastąpić starą %składnię formatowania. Ta ostatnia została pomniejszona (ale nie została jeszcze oficjalnie wycofana ). Dokumentacja metody stwierdza, że:

Ta metoda formatowania ciągów znaków jest nowym standardem w Pythonie 3 i powinna być preferowana względem %formatowania opisanego w Operacjach formatowania ciągów w nowym kodzie.

(Podkreślenie moje).

Aby zachować wsteczną kompatybilność i ułatwić przejście, stary format został pozostawiony w miejscu, do teraz . Z pierwotnej propozycji PEP 3101 :

Kompatybilność wsteczna

Zgodność wsteczną można zachować, pozostawiając istniejące mechanizmy na miejscu. Nowy system nie koliduje z żadną z nazw metod istniejących technik formatowania ciągów, więc oba systemy mogą współistnieć, dopóki nie nadejdzie czas na wycofanie starszego systemu.

Zwróć uwagę, dopóki nie przyjdzie czas na wycofanie starszego systemu ; nie został uznany za przestarzały, ale nowy system ma być używany za każdym razem, gdy piszesz nowy kod .

Zaletą nowego systemu jest to, że można połączyć krotkę i słownikowe podejście starego programu %formatującego:

"{greeting}, {0}".format(world, greeting='Hello')

i jest rozszerzalny za pomocą object.__format__()haka używanego do obsługi formatowania poszczególnych wartości.

Zauważ, że stary system miał %i Templateklasę, gdzie ta ostatnia pozwala na tworzenie podklas, które dodają lub zmieniają jego zachowanie. System nowego stylu ma Formatterklasę, która wypełnia tę samą niszę.

Python 3 dalej odszedł od wycofania, zamiast tego ostrzegając w sekcji printfFormatowanie ciągów w stylu :

Uwaga : Opisane tutaj operacje formatowania wykazują szereg dziwactw, które prowadzą do wielu typowych błędów (takich jak nieprawidłowe wyświetlanie krotek i słowników). Używanie nowszych sformatowanych literałów ciągów lub str.format()interfejsu pomaga uniknąć tych błędów. Te alternatywy zapewniają również bardziej wydajne, elastyczne i rozszerzalne podejście do formatowania tekstu.

Python 3.6 dodał również sformatowane literały ciągów , które wstawiają wyrażenia do ciągów formatu. Są to najszybsze metody tworzenia łańcuchów z wartościami interpolowanymi i powinny być używane zamiast str.format()wszędzie tam, gdzie można użyć literału.

Martijn Pieters
źródło
4
Dzięki temu Formattermożesz tworzyć niestandardowe formaty, takie jak te, których datetimeużywają obiekty. Ponadto, ponieważ .formatjest to funkcja, możesz jej użyć do bardziej bezpośredniego tworzenia wywoływalnego leniwego formatowania: np.fmt = '{} - {}'.format; fmt(a, b)
Jon Clements
Nie wiem, jak Templatejest powiązany %ze starym systemem lub z nim . W szczególności PEP, z którym łączysz, stany Chociaż istnieje pewne pokrywanie się między tą propozycją a string.Template, wydaje się, że każda z nich służy odrębnej potrzebie, a jedna nie wyklucza drugiej. W Twojej odpowiedzi można być zdezorientowanym, że Templateformatowanie, będące częścią starego systemu , również jest przestarzałe.
Bakuriu
@Bakuriu: Racja, myślę, że przegapiłem tę część; ale moim zdaniem Formatterklasa może zaspokoić te same potrzeby co string.Template().
Martijn Pieters
1
[...]should be preferred to the % formatting[...]ta część została usunięta z dokumentacji. docs.python.org/3/library/stdtypes.html#str.format
AXO,
Myślę, że ta odpowiedź jest obecnie myląca; pierwszy cytowany fragment został usunięty z dokumentacji Pythona 3 i wydaje mi się dość jasne, że nie ma już zamiaru, aby nastąpiło wycofanie. Ta odpowiedź nadal ma wartość historyczną, ale byłbym skłonny zmienić jej sformułowanie, aby uniknąć sugestii, że w kartach wciąż znajduje się deprecjacja, i zredagować większość pierwszej połowy odpowiedzi tak, aby była w czasie przeszłym. Zrobię to w pewnym momencie, jeśli nie sprzeciwiasz się, ale pomyślałem, że najpierw skomentuję, aby dać ci szansę na samodzielne wprowadzenie takich zmian, jeśli chcesz.
Mark Amery,
45

%Operator do formatowania ciąg nie jest przestarzała i nie zostanie usunięty - pomimo innych odpowiedzi.
Za każdym razem, gdy temat jest poruszany na liście deweloperów Pythona, istnieją silne kontrowersje, co do tego, co jest lepsze, ale nie ma kontrowersji, czy usunąć klasyczny sposób - pozostanie. Pomimo oznaczenia w PEP 3101, Python 3.1 pojawił się i zniknął, a %formatowanie wciąż istnieje.

Stwierdzenia dotyczące zachowania stylu klasycznego są jasne: jest proste, szybkie, szybkie do wykonania w przypadku krótkich rzeczy. Korzystanie z tej .formatmetody nie zawsze jest bardziej czytelne - i prawie nikt - nawet spośród głównych programistów, może użyć pełnej składni dostarczonej przez .formatbez konieczności patrzenia na odniesienie. Nawet w 2009 roku pojawiały się takie komunikaty: http: // mail. python.org/pipermail/python-dev/2009-October/092529.html - od tego czasu temat ledwo pojawiał się na listach.

Aktualizacja 2016

W obecnej wersji rozwojowej Pythona (która stanie się Pythonem 3.6) istnieje trzecia metoda interpolacji ciągów, opisana w PEP-0498 . To definiuje nowy prefiks ofertowe f""(oprócz prądu u"", b""ar"" ).

Prefiks ciągu przez f wywoła metodę na obiekcie ciągu w czasie wykonywania, która automatycznie interpoluje zmienne z bieżącego zakresu do ciągu:

>>> value = 80
>>> f'The value is {value}.'
'The value is 80.'
jsbueno
źródło
3
O wiele przyjemniej jest pozwolić typom na implementację własnych __format__. Na przykład, format(Decimal('0.1'), '.20f')vs '%.20f' % Decimal('0.1'). Ten ostatni wymusza Decimal na float.
Eryk Sun
2
NB. Nie twierdziłem, że stary styl jest lepszy pod każdym względem - po prostu jest krótszy, a czasem bardziej czytelny (a czasem nie). Z pewnością nowy sposób jest znacznie bardziej elastyczny.
jsbueno
Czy istnieje odpowiednik dla fw Pythonie 3?
Daniel
Zastosowane f-stringspowyżej są nową funkcją w języku od wersji Python 3.6. Nie istnieje w poprzednich wersjach i spowoduje w nich błąd składni.
jsbueno
20

Wydaje się, że ostatnie stanowisko Guido w tej sprawie jest wskazane tutaj:

Co nowego w Pythonie 3.0

PEP 3101: Nowe podejście do formatowania ciągów

Nowy system wbudowanych operacji formatowania ciągów zastępuje operator formatowania ciągu%. (Jednak operator% jest nadal obsługiwany; zostanie wycofany w Pythonie 3.1 i usunięty z języka później). Przeczytaj PEP 3101, aby uzyskać pełną informację.

I sam PEP3101 , który ma ostatnią modyfikację datowaną na (piątek, 30 września 2011), więc przypuszczam, że nie ma postępu w tej ostatniej.

GSP
źródło
18

Patrząc na starsze dokumenty Pythona i PEP 3101, było stwierdzenie, że operator% zostanie w przyszłości wycofany i usunięty z języka. Następujące stwierdzenie było w Dokumentach Pythona Pythonie 3.0, 3.1 i 3.2:

Ponieważ str.format () jest całkiem nowy, wiele kodu Pythona nadal używa operatora%. Jednakże, ponieważ ten stary styl formatowania zostanie ostatecznie usunięty z języka, generalnie powinna być używana str.format ().

Jeśli przejdziesz do tej samej sekcji w dokumentach Pythona 3.3 i 3.4, zobaczysz, że instrukcja została usunięta. Nie mogę również znaleźć żadnego innego stwierdzenia w dokumentacji nigdzie indziej wskazującego, że operator zostanie wycofany lub usunięty z języka. Należy również zauważyć, że PEP3101 nie był modyfikowany od ponad dwóch i pół roku (piątek, 30 września 2011).

Aktualizacja

PEP461 Dodawanie formatowania% do bajtów i bajtów jest akceptowane i powinno być częścią Pythona 3.5 lub 3.6. To kolejny znak, że operator% żyje i działa.

Marwan Alsabbagh
źródło