Dlaczego nawiasy w druku są dobrowolne w Pythonie 2.7?

98

W Pythonie 2.7 oba poniższe zrobią to samo

print("Hello, World!") # Prints "Hello, World!"

print "Hello, World!" # Prints "Hello, World!"

Jednak poniższe nie będą

print("Hello,", "World!") # Prints the tuple: ("Hello,", "World!")

print "Hello,", "World!" # Prints the words "Hello, World!"

W nawiasach Python 3.x on printjest obowiązkowy, co zasadniczo czyni go funkcją, ale w wersji 2.7 obie będą działać z różnymi wynikami. O czym jeszcze powinienem wiedzieć printw Pythonie 2.7?

Hubro
źródło
7
W Pythonie 2.x printjest właściwie instrukcją specjalną, a nie funkcją. Dlatego też nie można go używać w taki sposób, jak: lambda x: print xUwaga, (expr)która nie tworzy krotki (skutkuje expr), ale ,tak.
Zakładam, że obsługa drukowania jako funkcji i drukowania jako instrukcji ma na celu zachowanie wstecznej kompatybilności ze starszymi wersjami Pythona, jednocześnie zachęcając ludzi do korzystania z nowej składni w celu migracji do Pythona 3.
GWW
11
ps, Aby włączyć funkcję print w 2.7 (i nie mieć zachowania instrukcji print), musisz wykonać przyszły import:from __future__ import print_function
Jeff Mercado
Czy drugi przykład faktycznie wypisze "Hello, World!" (bez spacji), czy też wypisze „Hello, World!” (ze spacją) jak w przykładzie.
kapad

Odpowiedzi:

107

W Pythonie 2.x printjest właściwie instrukcją specjalną, a nie funkcją *.

Z tego powodu nie można go używać w następujący sposób: lambda x: print x

Zauważ, że (expr)nie tworzy krotki (skutkuje expr), ale ,tak. Prawdopodobnie powoduje to zamieszanie między print (x)iw print (x, y)Pythonie 2.7

(1)   # 1 -- no tuple Mister!
(1,)  # (1,)
(1,2) # (1, 2)
1,2   # 1 2 -- no tuple and no parenthesis :) [See below for print caveat.]

Ponieważ jednak w Pythonie 2.x printjest to specjalna instrukcja składniowa / konstrukcja gramatyki , to bez nawiasów traktuje znaki ,w specjalny sposób - i nie tworzy krotki. To specjalne traktowanie printinstrukcji umożliwia jej działanie w inny sposób, jeśli występuje na końcu ,lub nie.

Miłego kodowania.


* To printzachowanie w Pythonie 2 można zmienić na zachowanie w Pythonie 3:

from __future__ import print_function
user2357112 obsługuje Monikę
źródło
3
Dzięki za (expr) != tuplewyjaśnienie :-)
Hubro
5

To wszystko jest bardzo proste i nie ma nic wspólnego z kompatybilnością wsteczną lub wsteczną.

Ogólna forma printinstrukcji we wszystkich wersjach Pythona przed wersją 3 to:

print expr1, expr2, ... exprn

(Każde wyrażenie jest po kolei oceniane, konwertowane na ciąg i wyświetlane ze spacją między nimi).

Pamiętaj jednak, że umieszczanie nawiasów wokół wyrażenia to wciąż to samo wyrażenie.

Możesz więc również napisać to jako:

print (expr1), (expr2), ... (expr3)

Nie ma to nic wspólnego z wywołaniem funkcji.

Don O'Donnell
źródło
To jest całkowicie poprawna odpowiedź, nie jestem też pewien, dlaczego tak bardzo ją odrzucono.
Martijn Pieters
Nie chodzi o print (expr1), (expr2), ... (expr3)to, dlaczego print (expr1, expr2, ... , expr3)jest legalny w Pythonie 2.x, a nie powinien być zgodny ze standardami 2.x.
vinnief
5

Tutaj mamy ciekawy efekt uboczny, jeśli chodzi o UTF-8.

>> greek = dict( dog="σκύλος", cat="γάτα" )
>> print greek['dog'], greek['cat']
σκύλος γάτα
>> print (greek['dog'], greek['cat'])
('\xcf\x83\xce\xba\xcf\x8d\xce\xbb\xce\xbf\xcf\x82', '\xce\xb3\xce\xac\xcf\x84\xce\xb1')

Ostatni wydruk to krotka z szesnastkowymi wartościami bajtów.

Karlo Smid
źródło
7
Zakładam, że dzieje się tak dlatego, że print drukuje poprawnie UTF-8, ale kiedy otrzyma krotkę, tak jak twój ostatni wydruk, działa reprna niej, w którym to momencie prawdopodobnie koduje wszystkie ciągi w dykt do ASCII.
Hubro
3
@Codemonkey, masz rację co do repr . Mylisz się co do ASCII. ASCII jest domyślnym kodowaniem dla Pythona. Ale mam na początku skrypt w Pythonie #encoding=utf-8, linux env LANG=en_US.UTF-8. Więc repr koduje nie używając domyślnego ASCII, ale kodowania utf-8.
Karlo Smid
1
Ponownie koduje strze specjalnym string_escapekodowaniem. Ciąg był już zakodowany w Unicode jako UTF-8.
tzot
@KarloSmid: Chodziło mi o to, że reprprawdopodobnie podejmuje kroki w celu zapewnienia, że ​​tekst może być reprezentowany przez ASCII (za pomocą znaków ucieczki znaków spoza ASCII), niekoniecznie że ciąg jest zakodowany jako ASCII. Nadal nie wiem, czy to jest całkowicie dokładne.
Hubro
Wszystkie kontenery Pythona (list, dict, tuple, set) zawierają swoją zawartość jako repr()dane wyjściowe po przekonwertowaniu na łańcuch (nie implementują __str__, tylko __repr__). To, co widzisz, nie jest wyjątkowe w UTF-8; the repr()string daje poprawne literały łańcuchowe Pythona, które są bezpieczne dla ASCII.
Martijn Pieters
2

Zasadniczo w Pythonie przed Pythonem 3 print był specjalną instrukcją, która wyświetlała wszystkie ciągi znaków, jeśli otrzymano je jako argumenty. Czyli print "foo","bar"po prostu oznaczało „print 'foo', a następnie 'bar'”. Problem z tym było to było kuszące, aby działać tak, jakby były funkcją drukowania, a gramatyka Python jest niejednoznaczna na tym, ponieważ (a,b)jest krotką zawierającą aa bjednak foo(a,b)to wywołanie funkcji dwóch argumentów.

Dlatego wprowadzili niekompatybilną zmianę dla 3, aby programy były mniej niejednoznaczne i bardziej regularne.

(Właściwie myślę, że 2.7 zachowuje się tak jak 2.6 w tym, ale nie jestem pewien.)

Charlie Martin
źródło
Nie, używanie go jako funkcji nie było „kuszące”. :) Jednak niemożliwe było użycie tego jako funkcji, więc nie możesz na przykład [wypisać x dla x w liście].
Lennart Regebro