Разработка под Python 2+3 — Intermediate Python
Во многих случаях вам может понадобиться писать программы, которые будут корректно работать и на Python 2+ и на 3+.
Представьте, что у вас есть крайне популярный Python-пакет, который используют тысячи людей, но не у всех есть Python 2 или Python 3. В этом случае у вас есть два варианта. Первый — разрабатывать две версии параллельно, одну для второй ветки Python, а другую — для третьей. Другим вариантом будет изменение текущего кода для совместимости как с Python 2, так и с Python 3.
В данном разделе я собираюсь рассказать о нескольких приёмах, которые вы можете использовать, чтобы сделать скрипт совместимым с обоими ветками Python.
Импорты Future
Первым и наиболее важным методом будет использование импорта __future__
. Это позволяет вам импортировать функционал Python 3 в Python 2. Ниже несколько примеров.
Менеджеры контекста были нововведением в Python 2.6+. Для их использования в Python 2.5 вам необходимо:
from __future__ import with_statement
print
стал функцией в Python 3. Для её использования в Python 2 вы можете импортировать функцию из __future__
:
# Вывод:
from __future__ import print_function
print(print)
# Вывод: <built-in function print>
Переименование модулей
Для начала, скажите мне как вы импортируете модули в ваших скриптах? Большинство делает так:
import foo
from foo import bar
А знаете ли вы про такой способ:
import foo as foo
Я знаю, что эффект будет такой же, как и в первом случае, но этот способ критичен для совместимости программ с Python 2 и 3. Попробуем следующий код:
import urllib.request as urllib_request # для Python 3
except ImportError:
import urllib2 as urllib_request # для Python 2
Позвольте мне немного пояснить. Мы используем блок try/except
для импорта. Причина — в Python 2 нет модуля urllib.request
, поэтому попытка его импорта приведет к ImportError
. Функциональность urllib.request
доступна в модуле urlib2
в Python 2. Таким образом, при использовании Python 2, при импорте urllib. request
мы упираемся в Exception и импортируем urllib2
в качестве альтернативы.
Последнее что вам нужно знать — ключевое слово as
. С его помощью мы импортируем модуль под именем urllib_request
. Дальше в коде мы просто будем ссылаться на это имя, вне зависимости от того, какую ветку Python мы используем.
Заменяем устаревшие модули Python 2
В Python 2 есть 12 устаревших модулей, которые были удалены в Python 3. Для сохранения совместимости убедитесь, что не используете их в своем коде. Следующим образом можно явно запретить использование удаленного в Python 3 функционала:
from future.builtins.disabled import *
Теперь, при использовании удаленного в Python 3 модуля, мы будем получать NameError
:
from future. builtins.disabled import *
apply()
# Вывод: NameError: obsolete Python 2 builtin apply is disabled
Сторонние бэкпорты
Существует несколько пакетов, которые предоставляют новый функционал Python 3 в Python 2. Например:
enum
pip install enum34
singledispatch
pip install singledispatch
pathlib
pip install pathlib
В качестве дополнительного чтения: официальная документация содержит исчерпывающее руководство, объясняющее шаги, которые вам нужно предпринять для гарантии совместимости кода с обеими ветками Python.
Почему print(«Hello») работает в Python 2
Одним из самых заметных отличий Python 3 от Python 2 является разжалование print
из инструкции языка (statement) до обычной функции.
Python 3:
# простое использование print("Hello") # выводит: Hello # переданные аргументы по умолчанию объединяются через пробел print("Hello", "world!") # выводит: Hello world! # объединяющий символ можно заменить на свой print("Pythonic", "attacks!", sep="_") # выводит: Pythonic_attacks! # можно заменить символ конца строки на пустую строку, # чтобы продолжить выводить что-нибудь в той же строке print("Hello ", end="") print("world!") # выводит: Hello world!
Python 2:
# простое использование print "Hello" # выводит: Hello # перечисленные аргументы объединяются через пробел print "Hello", "world!" # выводит: Hello world! # если нужен не пробел, а другой символ для объединения, # то остаётся делать только вот так: print "_".join(["Hello", "world!"]) # выводит: Hello_world! # можно при помощи запятой в конце избежать вывода \n (символа конца строки) # и продолжить печатать что-нибудь на той же строке: print "Hello", print "world!" # выводит: Hello world! # если сделать специальный импорт из “будущего”, то # в Python 2.6+ `print` начинает работать как функция: from __future__ import print_function print("Hello", "world!") # выводит: Hello world!
Обычно инструкциями в Python являются только очень базовые вещи,
такие как условия (if
), циклы (for
, while
),
возврат из функций (return
) и т.д.
Преобразование print
в функцию было сделано
во имя упрощения синтаксиса языка.
Инструкция
для работы требовала значительного количества синтаксических
конструкций, например, для отсутствия символа переноса строки (,
) или
перенаправления вывода в файл (>>
).
Всё это можно было заставить играть по общим правилам
(и даже значительно расширить функционал) через позиционные и именованные
аргументы функций, вообще без какого-либо расширения синтаксиса языка.
Кроме того, print
как функцию можно использовать гораздо гибче — например,
фиксируя часть аргументов
(каррирование)
через functools. partial
или использовать её в других функциях (передавать саму функцию как аргумент), типа
или filter()
.
Недавно в исходниках библиотеки logging_tree
я увидел, что print
используется как функция
без каких-либо импортов из будущего, при этом у библиотеки
заявлена поддержка версий Python,
начиная аж с 2.3:
print(build_description(node)[:-1])
Меня это удивило. Я даже
создал пулл-реквест,
будучи уверен, что нашёл ошибку. После того, как автор возразил,
что к нему не поступало никаких жалоб по поводу такого использования print
,
я решил всё-таки проверить, как это работает.
И к ещё большему моему удивлению, это и правда работало на всех версиях Python
2, до которых я смог дотянуться, включая 2.7, 2.6, 2.5, 2.4 и даже 2.3:
# как?? print("Hello") # выводит: Hello
Немного поразмыслив и почитав, я осознал, где тут собака зарыта.
Хоть это и выглядит как вызов функции print()
, на самом деле это всё та же
старая добрая инструкция print
. Давайте разложим всё по полочкам:
# сначала отодвинем скобки от print, чтобы было нагляднее, что это инструкция: print ("Hello") # выводит: Hello # в Python можно засунуть в скобки любое выражение, но пока оно там одно, # то скобки не оказывают никакого влияния: ("Hello") # получается просто строка: 'Hello' # а если выражений несколько, или там есть запятая, то тогда уже # создаётся кортеж: ("Hello",) # кортеж из одного элемента ("Hello", "world") # кортеж из двух элементов # в нашем случае выражение только одно, поэтому скобки можно отбросить: print "Hello" # выводит: Hello
Как выяснилось, в Python 2 print
и правда можно так, что со стороны это будет
выглядеть как вызов функции, но для очень ограниченного множества случаев,
а именно — должен быть только один позиционный аргумент.
Такой код будет успешно выполняться и на Python 2 (благодаря описанному трюку),
и на Python 3 (по-настоящему).
Разница становится очевидной, если попытаться узнать тип:
# у инструкций нельзя запросить тип, это синтаксически невозможно >>> type(print) File "<stdin>", line 1 type(print) ^ SyntaxError: invalid syntax # а у функций можно >>> from __future__ import print_function >>> type(print) <type 'builtin_function_or_method'>
Трюки из той же серии:
# условие со скобками как в C: >>> if(1 == 1): . .. print("Equal!") ... Equal! # return как функция: >>> def func(): ... return(True) ... >>> func() True
Это код синтаксически верен, но просто обычно так не пишут. И правильно.
Python 2.7 недавно получил свой последний релиз с исправлениями ошибок, и больше никогда не будет обновляться — даже новые найденные баги, связанные с безопасностью, не будут пофикшены. Хочется верить, что все заинтересованные уже обновились до Python 3, и никто больше активно не использует Python 2, в 2020-то году. К сожалению, вряд ли это так. Боюсь, что предсмертная агония Python 2 продлится ещё как минимум несколько лет. Поэтому знать про него хотя бы что-то всё равно полезно.
Благодаря этому случаю я узнал про странный трюк с print
и извлёк урок,
что нужно как минимум проверять свой фикс, прежде чем засылать куда-то
пулл-реквест.
Если понравилась статья, то подпишитесь на уведомления о новых постах в блоге, чтобы ничего не пропустить!
- Большой гайд про print на RealPython;
- Брэтт Кэннон, «Why
print
became a function in Python 3″.
Обложка: Photo by mali maeder from Pexels
python — Использование print() (версия функции) в Python2.x
спросил
Изменено 5 лет, 2 месяца назад
Просмотрено 63к раз
Я понимаю разницу между оператором и выражением и понимаю, что Python3 превратил функцию print() в функцию.
Однако я запускал оператор print(), заключенный в круглые скобки, в различных интерпретаторах Python2.x, и он работал безупречно, мне даже не пришлось импортировать какой-либо модуль.
Мой вопрос: следующий код print("Hello SO!")
оценивается как оператор или выражение в Python2.x?
- python
- печать
- python-2.x
- вызов функции
Рассмотрим следующие выражения:
a = ("Hello SO!") a = "Привет ТАК!"
Они эквивалентны. Точно так же с оператором:
statement_keyword("foo") оператор_ключевое слово "foo"
также эквивалентны.
Обратите внимание, что если вы измените функцию печати на:
print("Hello","SO!")
Вы заметите разницу между Python 2 и Python 3. В Python 2 (...,...)
интерпретируется как кортеж, поскольку print является оператором, тогда как в Python 3 это вызов функции. с несколькими аргументами.
Поэтому, чтобы ответить на поставленный вопрос, print
оценивается как оператор в python 2.x, если только вы не из __future__ import print_function
(представлено в python 2.6)
2
print("Hello SO!")
оценивается как оператор print ("Hello SO!")
, где аргументом оператора print
является выражение ("Hello SO!")
.
Это может иметь значение, если вы печатаете более одного значения; например print("Hello", "world")
напечатает двухэлементный кортеж ("Hello", "world")
вместо двух строк "Hello"
и "world"
.
Для совместимости с Python 3 используйте из __future__ import print_function
:
>>> print("Hello", "world") ('Привет, мир') >>> из __future__ импортировать print_function >>> print("Привет", "мир") Привет, мир
2
Он по-прежнему оценивается как оператор, вы просто печатаете ("Привет, ТАК!")
, который просто оценивается как "Привет, ТАК!"
, так как это не кортеж (как упоминал delnan).
3
Зарегистрируйтесь или войдите в систему
Зарегистрируйтесь с помощью Google
Зарегистрироваться через Facebook
Зарегистрируйтесь, используя электронную почту и пароль
Опубликовать как гость
Электронная почта
Требуется, но никогда не отображается
Опубликовать как гость
Электронная почта
Требуется, но не отображается
В чем разница между print и print() в python 2.
7спросил
Изменено 1 месяц назад
Просмотрено 80 тысяч раз
Я новичок в Python.
Я запускаю следующий код на python 2.7 и вижу другой результат, когда использую print или print(). В чем разница между этими двумя функциями? Я читал другие вопросы, например, этот вопрос, но не нашел своего ответа.
класс Прямоугольник: def __init__(я, ш, ч): собственная ширина = ш собственная высота = h защита __str__(я): return "(Ширина: {0}, а высота: {1})".format(self.width, self.height) поле = прямоугольник (100, 200) печать ("коробка: ", коробка) напечатать "коробка:", коробка
Результат:
('box:', <__main__.Экземпляр прямоугольника по адресу 0x0293BDC8>) box: (ширина: 100, высота: 200)
- питон
- питон-2. 7
1
В Python 2.7 (и более ранних версиях) print
— это оператор , который принимает ряд аргументов. Он печатает аргументы с пробелом между ними.
Итак, если вы наберете
, напечатайте «box:», box
Сначала печатается строка «box:», затем пробел, затем любое поле
, которое печатается как (результат его функции __str__
).
Если вы напечатаете
("box:", box)
Вы передали один аргумент, кортеж, состоящий из двух элементов («box:» и объект box
).
Кортежи печатаются как их представление (в основном используются для отладки), поэтому он вызывает __repr__
своих элементов, а не их __str__
(что должно давать удобное для пользователя сообщение).
Вот разница, которую вы видите: (Ширина: 100, а высота: 200)
__str__
, но <__main__. Экземпляр прямоугольника по адресу 0x0293BDC8>
— это его __repr__
. В Python 3 и более поздних версиях print()
является нормальной функцией, как и любая другая (поэтому print(2, 3)
печатает "2 3"
, а print 2, 3
является синтаксической ошибкой). Если вы хотите иметь это в Python 2.7, введите
из __future__ import print_function
в верхней части исходного файла, чтобы сделать его немного более готовым к настоящему.
Это в основном дополнение к другим ответам.
Вы можете увидеть в сценариях Python 2 print (var)
, когда обычно используется print var
.
Он использует тот факт, что (var)
— это просто выражение в скобках в Python 2, которое просто рассматривается как var
, поэтому print(var)
и print var
ведут себя точно так же в Python 2, но только работает при печати одной единственной переменной
Интересно, что при переходе на Python 3, print(var)
(здесь вызов функции print) уже является правильным синтаксисом.
TL/DR: print(var)
в Python 2 — это просто уловка, облегчающая миграцию на Python3 с использованием того факта, что (var)
— это просто выражение — форма кортежа будет (var,)
В первом примере вы печатаете кортеж, но не вызываете функцию печати. Таким образом, следующее идентично:
a = ("box: ", box) распечатать
Другими словами, в первом примере вы создали кортеж и распечатали его. Разный вывод для разных типов данных.
В вашем случае не должно быть существенной разницы между функцией и оператором, но на будущее я настоятельно рекомендую вам всегда использовать функцию (
). Однако, если вас все еще интересуют различия (не связанные с вашим случаем), с помощью функции печати вы можете указать разделитель, конец и куда его выводить, как описано в документации.
2
В Python 2.7 print() работает быстрее, чем print. Вот тест, сделанный с помощью Repl.it Python Console Online:
время импорта start_time = время.время() печатать "лол" end_time = время.время() печать (конечное_время - начальное_время) start_time_2 = время.время() распечатать ("лол") end_time_2 = время.время() печать (конец_время_2 - начало_время_2) print((end_time_2 - start_time_2) >(end_time - start_time)) Питон 2.7.10 [GCC 4.8.2] в Linux ржу не могу 7.08103179932э-05 ржу не могу 1.00135803223э-05 ЛОЖЬ
2
В Python 2.7: print — это не функция, это ключевое слово и действует как специальный оператор.
Перед этим нам нужно больше узнать о tuple и expr в python2.
Если мы напишем («привет»): это рассматривается как выражение, а не как кортеж, его можно рассматривать как кортеж, только если введено «,».
print("привет") >>> привет а=("привет") >>> "привет" а=("привет", "мир") >>>('привет', "мир") print("привет", "мир") >>> («привет», «мир»)
, поэтому в python2.