Чому дужки в друку добровільні в 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?


7
У Python 2.x printнасправді є спеціальним оператором, а не функцією. Ось чому його не можна використовувати так: lambda x: print xЗауважте, що (expr)не створюється кортеж (це призводить до expr), але ,робить.

Я припускаю, що підтримка друку як функції та друку як висловлювання полягає у підтримці зворотної сумісності зі старими версіями python, заохочуючи людей використовувати новий синтаксис для міграції до python 3.
GWW

11
ps, Щоб увімкнути функцію друку в 2.7 (і не мати поведінки оператора друку), потрібно виконати майбутній імпорт:from __future__ import print_function
Джефф Меркадо,

Чи буде другий приклад насправді надрукувати "Привіт, світ!" (без пробілу) або надрукує "Привіт, світ!" (з пробілом), як у прикладі.
капад

Відповіді:


106

У 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 особливим чином - і не створює Tuple. Ця спеціальна трактування printтвердження дозволяє йому діяти по-різному, якщо є зворотний зв'язок ,чи ні.

Щасливе кодування.


* Ця printповедінка в Python 2 може бути змінена до поведінки в Python 3:

from __future__ import print_function

3
Дякую за (expr) != tupleпояснення :-)
Hubro

5

Все дуже просто і не має нічого спільного з прямою або зворотною сумісністю.

Загальна форма printзаяви у всіх версіях Python до версії 3 така:

print expr1, expr2, ... exprn

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

Але пам’ятайте, що розміщення дужок навколо виразу - це все той самий вираз.

Тож ви також можете написати це як:

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

Це не має нічого спільного з викликом функції.


Це цілком правильна відповідь, я не впевнений, чому так сильно заперечували.
Martijn Pieters

Йдеться не про те 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
Я припускаю, що це тому, що друк правильно друкує UTF-8, але коли він отримує кортеж, як ваш останній друк, він запускається reprна ньому, і тоді він, мабуть, кодує всі рядки в дикті до ASCII.
Хубро

3
@Codemonkey, ти прав про репр . Ви помиляєтесь щодо ASCII. ASCII - це кодування за замовчуванням для Python. Але у мене є на початку сценарій Python #encoding=utf-8, linux env LANG=en_US.UTF-8. Отже, repr кодує не використовуючи ASCII за замовчуванням, а кодування utf-8.
Карло Смід

1
Repr кодує strза допомогою спеціального string_escapeкодування. Рядок уже був закодований як UTF-8.
tzot

@KarloSmid: Те , що я хотів сказати , що , reprймовірно , вживає заходів для забезпечення того, що текст може бути представлений ASCII (з допомогою втечі , НЕ-ASCII символів), не обов'язково , що рядок буде кодуватися як ASCII. Я досі не знаю, чи це абсолютно точно.
Хубро

Усі контейнери Python (list, dict, tuple, set) включають свій вміст як repr()вихідний файл при перетворенні у рядок (вони не реалізуються __str__, лише __repr__). Те, що ви бачите, не є особливим для UTF-8; repr()рядки дають дійсні рядкові літерали Python , які є ASCII-сейф.
Martijn Pieters

2

В основному в Python перед Python 3, print - це спеціальний вислів, який друкував усі рядки, якщо їх отримували як аргументи. Так print "foo","bar"просто малося на увазі "надрукувати" foo ", а потім" bar "". Проблема з цим було було заманливо діяти , як якщо б друк була функція, а граматика Python неоднозначна на те , що, так як (a,b)це кортеж , що містить aі , bале foo(a,b)це виклик функції двох аргументів.

Тому вони внесли несумісну зміну для 3, щоб зробити програми менш неоднозначними та більш регулярними.

(Власне, я думаю, що 2,7 поводиться так, як 2,6 робив це, але я не впевнений.)


Ні, не було "спокусою" використовувати його як функцію. :) Однак використовувати його як функцію було неможливо, тому ви не можете зробити [print x for x в alist], наприклад.
Леннарт Регебро
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.