Python 2: основные конструкции и примеры
Основные конструкции Python 2
Наиболее эффективный способ писать код на Python 2, готовый к переносу на Python 3 - применение директив из модуля __future__. Импорт print_function, division, absolute_import и unicode_literals делает поведение близким к Python 3.
from __future__ import print_function, division, absolute_import, unicode_literals
print("Hello, World!") # функция
print(5/2) # 2.5
print(5//2) # 2Python 2 примеры (примеры кода на python 2)
Этот подход рекомендуется для всех новых скриптов, даже если они предназначены для Python 2, поскольку упрощает будущую миграцию.
Частая ошибка - забыть импортировать division и получить целочисленное деление. Другая проблема - импорт unicode_literals может привести к конфликтам с библиотеками, ожидающими str. В таких случаях стоит использовать явные префиксы b для байтовых строк.
Как получить пользовательский ввод в Python 2?
Функция raw_input возвращает строку, а input пытается выполнить eval() введённого выражения. Для безопасного ввода следует использовать raw_input:
name = raw_input("Введите имя: ")
print "Привет,", name
age = int(raw_input("Сколько лет? "))
Ошибка: использование input вводит уязвимость к выполнению произвольного кода. Решение - всегда применять raw_input и преобразовывать к нужному типу.
Как использовать диапазон чисел без создания списка?
В Python 2 range возвращает список, что неэффективно при больших числах. Функция xrange возвращает итератор, экономя память:
for i in xrange(1000000):
pass
Для совместимости с Python 3 можно импортировать range из __future__.
Забывчивость: если используется range в большом цикле, память быстро расходуется. Решение - замена на xrange.
Как обрабатывать строки в юникоде?
В Python 2 строки по умолчанию - байтовые. Для работы с Unicode используется префикс u:
s = u"Привет, мир!"
print s
b = s.encode('utf-8')
print b
При импорте unicode_literals все строки без префикса становятся Unicode.
Типичная ошибка - UnicodeDecodeError при смешении байтовых и Unicode строк. Решение: чётко разделять типы, использовать decode и encode.
Как перехватить исключение с сохранением объекта?
В Python 2 синтаксис except Exception, e связывает переменную e. Более новый стиль except Exception as e также работает в Python 2 (начиная с 2.6):
try:
1/0
except ZeroDivisionError as e:
print "Ошибка:", e
Вариант с запятой тоже допустим, но менее читаем.
Использование старого синтаксиса с запятой может привести к синтаксической ошибке в Python 3. Рекомендуется as.
Как определить класс старого стиля?
Классы без явного наследования от object считаются старыми (classic classes). Новые классы наследуют от object:
class OldStyle:
pass
class NewStyle(object):
pass
Новые классы поддерживают super, свойства, дескрипторы. Для совместимости с Python 3 рекомендуется всегда наследовать от object.
Если класс не наследует от object, его методы __getattribute__ и другие ведут себя иначе.
Как использовать итераторы map, filter, zip в Python 2?
Эти функции возвращают списки. Для ленивых вычислений используйте модуль itertools (imap, ifilter, izip):
from itertools import imap, ifilter, izip
data = [1,2,3,4]
result = list(imap(lambda x: x*2, data))
Также map(None, ...) использовалось для zip разной длины.
Замена map на imap в большом наборе данных экономит память, но не возвращает список.
Как открыть файл с указанием кодировки?
Модуль codecs предоставляет функцию open для работы с кодировками:
import codecs
with codecs.open('file.txt', 'w', encoding='utf-8') as f:
f.write(u"Привет")
with codecs.open('file.txt', 'r', encoding='utf-8') as f:
content = f.read()
В Python 3 используется встроенный open с параметром encoding.
Использование встроенного open без кодировки приводит к получению байтовой строки.
Как получить список ключей словаря в порядке вставки?
В Python 2.7 появился OrderedDict из модуля collections. Обычный словарь не гарантирует порядок (хотя в CPython 2.7 порядок совпадает с вставкой, но это деталь реализации).
from collections import OrderedDict
d = OrderedDict()
d['a'] = 1
d['b'] = 2
for k, v in d.items():
print k, v
Полагаться на порядок обычного словаря не следует, так как это поведение не документировано.
Как вывести отладочную информацию в stderr?
Используется sys.stderr.write или print>>sys.stderr:
import sys
print >> sys.stderr, "Ошибка: ..."
sys.stderr.write("Ошибка: ...\n")
В Python 3 print(..., file=sys.stderr).
Забыть про >> и использовать обычный print - сообщение уходит в stdout.
Все перечисленные примеры охватывают ключевые отличия Python 2 от более новых версий. Каждый вариант предназначен для решения определённой задачи: обеспечение совместимости, работа с вводом-выводом, обработка данных, определение классов. Знание этих конструкций необходимо при поддержке существующих проектов на Python 2.
Генератор чисел Фибоначчи
def fib():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
f = fib()
for _ in xrange(10):
print f.next(),
0 1 1 2 3 5 8 13 21 34
Работа с JSON (simplejson)
import simplejson as json
data = {'name': u'Иван', 'age': 30}
json_str = json.dumps(data, ensure_ascii=False)
print json_str
parsed = json.loads(json_str)
print parsed['name']
HTTP запрос через urllib2
import urllib2
req = urllib2.Request('http://httpbin.org/get')
response = urllib2.urlopen(req)
print response.read()[:100]
Обход файлов с os.walk
import os
for root, dirs, files in os.walk('/tmp'):
for name in files:
if name.endswith('.txt'):
print os.path.join(root, name)
Использование threading
import threading, time
def worker():
print "Поток запущен"
time.sleep(1)
print "Поток завершён"
threads = []
for i in range(3):
t = threading.Thread(target=worker)
t.start()
threads.append(t)
for t in threads:
t.join()
Сортировка с operator.itemgetter
from operator import itemgetter
data = [('Вася', 25), ('Петя', 20), ('Аня', 30)]
sorted_data = sorted(data, key=itemgetter(1))
print sorted_data
[('Петя', 20), ('Вася', 25), ('Аня', 30)]
Работа с pickle
import pickle
obj = {'a': [1,2,3], 'b': 'hello'}
with open('data.pkl', 'wb') as f:
pickle.dump(obj, f)
with open('data.pkl', 'rb') as f:
loaded = pickle.load(f)
print loaded
{'a': [1, 2, 3], 'b': 'hello'}