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?


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

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.


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.


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.)


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.