Почему круглые скобки в Python 2.7 являются добровольными?

98

В Python 2.7 следующее будет делать то же самое

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

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

Однако следующее не будет

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

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

В Python 3.x круглые скобки printявляются обязательными, что, по сути, делает их функцией, но в 2.7 оба будут работать с разными результатами. Что еще мне нужно знать о printPython 2.7?

Hubro
источник
7
В Python 2.x printэто на самом деле специальный оператор, а не функция. Вот почему его нельзя использовать как: lambda x: print xОбратите внимание, что (expr)кортеж не создается (результат получается expr), но создается ,.
Я предполагаю, что поддержка print как функции и print как оператора предназначена для поддержания обратной совместимости со старыми версиями python, поощряя людей использовать новый синтаксис для перехода на python 3.
GWW
11
ps, Чтобы включить функцию печати в 2.7 (и не иметь поведения оператора печати), вам необходимо выполнить будущий импорт:from __future__ import print_function
Джефф Меркадо,
Будет ли второй пример на самом деле печатать "Hello, World!" (без пробела) или напечатает «Hello, World!» (с пробелом) как в примере.
капад 06

Ответы:

107

В Python 2.x printэто фактически специальный оператор, а не функция *.

Вот почему его нельзя использовать как: lambda x: print x

Обратите внимание, что (expr)кортеж не создается (результат получается expr), но создается ,. Это, вероятно, приводит к путанице между print (x)и print (x, y)в Python 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.]

Однако, поскольку printэто специальный синтаксический оператор / грамматическая конструкция в Python 2.x, то без круглых скобок он обрабатывает ,'s особым образом - и не создает кортеж. Эта особая обработка printоператора позволяет ему действовать по-разному, независимо от того, есть ли завершающий элемент ,или нет.

Удачного кодирования.


* Это printповедение в Python 2 можно изменить на поведение Python 3:

from __future__ import print_function
user2357112 поддерживает Монику
источник
3
Спасибо за (expr) != tupleобъяснение :-)
Hubro
5

Все очень просто и не имеет ничего общего с прямой или обратной совместимостью.

Общая форма printоператора во всех версиях Python до версии 3:

print expr1, expr2, ... exprn

(Каждое выражение по очереди вычисляется, преобразуется в строку и отображается с пробелом между ними.)

Но помните, что заключение выражения в круглые скобки остается тем же выражением.

Вы также можете написать это как:

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

Это не имеет ничего общего с вызовом функции.

Дон О'Доннелл
источник
Это совершенно правильный ответ, я тоже не уверен, почему его так сильно отвергли.
Мартин Питерс
Это не о том print (expr1), (expr2), ... (expr3), а о том, почему print (expr1, expr2, ... , expr3)это законно в python 2.x, в то время как это не должно соответствовать стандартам 2.x.
vinnief
5

Здесь у нас есть интересный побочный эффект, когда дело доходит до 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')

Последний вывод - кортеж с шестнадцатеричными байтовыми значениями.

Карло Смид
источник
7
Я предполагаю, что это потому, что print печатает UTF-8 правильно, но когда он получает кортеж, как ваш последний print, он запускается reprна нем, и в этот момент он, вероятно, кодирует все строки в dict в ASCII.
Hubro
3
@Codemonkey, ты прав насчет репр . Вы ошибаетесь насчет ASCII. ASCII - это кодировка по умолчанию для Python. Но у меня в начале Python скрипт #encoding=utf-8linux env LANG=en_US.UTF-8. Таким образом, repr кодирует не используя кодировку ASCII по умолчанию, а кодировку utf-8.
Карло Смид
1
Repr кодируется strспециальной string_escapeкодировкой. Строка уже была закодирована в Юникоде как UTF-8.
tzot 02
@KarloSmid: Я хотел сказать, что, reprвероятно, предпринимаются шаги, чтобы гарантировать, что текст может быть представлен ASCII (посредством экранирования не-ASCII-символов), не обязательно, чтобы строка была закодирована как ASCII. Я до сих пор не знаю, верно ли это.
Hubro
Все контейнеры Python (список, ДИКТ, кортеж, набор) включают их содержимое , как repr()выход при преобразовании в строку (они не выполняют __str__, только __repr__). То, что вы видите, не является особенным для UTF-8; the repr()строки дает вам допустимые строковые литералы Python, которые безопасны для ASCII.
Мартин Питерс
2

В основном в Python до Python 3 print был специальным оператором, который печатал все строки, если они были получены в качестве аргументов. Это print "foo","bar"просто означало «напечатать 'foo', за которым следует 'bar» ». Проблема заключалась в том, что было заманчиво действовать так, как если бы print была функцией, и грамматика Python неоднозначна, поскольку (a,b)это кортеж, содержащий aи, bно foo(a,b)являющийся вызовом функции двух аргументов.

Поэтому они внесли несовместимое изменение для 3, чтобы сделать программы менее неоднозначными и более регулярными.

(На самом деле, я думаю, что 2.7 ведет себя так же, как 2.6, но я не уверен.)

Чарли Мартин
источник
Нет, это не было «искушением» использовать его как функцию. :) Однако использовать его как функцию было невозможно, поэтому вы не можете, например, [напечатать x вместо x в alist].
Леннарт Регебро