Разработка под 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. мы упираемся в Exception и импортируем
requesturllib2 в качестве альтернативы.
Последнее что вам нужно знать — ключевое слово 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 enum34singledispatch
pip install singledispatchpathlib
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
printbecame 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.


.. print("Equal!")
...
Equal!
# return как функция:
>>> def func():
... return(True)
...
>>> func()
True

7
Экземпляр прямоугольника по адресу 0x0293BDC8>