← Назад к вопросам

Какие особенности и ограничения были в Python 2 по сравнению с более поздними версиями?

1.6 Junior🔥 61 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Особенности и ограничения Python 2 по сравнению с Python 3

Python 2 был выпущен в октябре 2000 года и официально прекратил поддержку 1 января 2020 года. Несмотря на это, до сих пор есть legacy-проекты, работающие на Python 2. Понимание различий важно для работы с такими кодовыми базами и миграции на Python 3.

Различия в типах и строках

Unicode vs Bytes

Python 2:

# Строка по умолчанию — это bytes (ASCII)
s = "hello"  # type: str (на самом деле bytes)
print(type(s))  # <type 'str'>

# Unicode требует префикса u
u = u"hello"  # type: unicode
print(type(u))  # <type 'unicode'>

# Конкатенация может быть проблематичной
result = "hello" + u"мир"  # UnicodeDecodeError!

# Кодирование/декодирование требуется явно
encoded = "hello".encode('utf-8')  # bytes
decoded = u"hello".decode('utf-8')  # ошибка - unicode не имеет decode

Python 3:

# Строка по умолчанию — это unicode
s = "hello"  # type: str (unicode)
print(type(s))  # <class 'str'>

# Префикс u опционален (добавлен обратно в Python 3.3 для совместимости)
u = u"hello"  # type: str (то же самое)

# Конкатенация работает всегда
result = "hello" + "мир"  # "helloмир"

# Явное разделение между str и bytes
b = b"hello"  # type: bytes
s = "hello"  # type: str
encoded = "hello".encode('utf-8')  # bytes
decoded = b"hello".decode('utf-8')  # str

Integer Division

Python 2:

result = 5 / 2  # 2 (целочисленное деление по умолчанию)
float_result = 5.0 / 2  # 2.5 (нужен float для деления с остатком)
float_result = 5 / 2.0  # 2.5

Python 3:

result = 5 / 2  # 2.5 (всегда деление с остатком)
int_result = 5 // 2  # 2 (целочисленное деление явное)

Основные функции

print

Python 2:

# print — это statement, не функция
print "hello"
print "hello", "world"  # Разделитель — пробел
print "hello",  # Запятая подавляет newline
print >> sys.stderr, "error"  # Вывод в stderr

Python 3:

# print — это функция
print("hello")
print("hello", "world")  # Разделитель — пробел
print("hello", end="")  # Подавляет newline
print("error", file=sys.stderr)  # Вывод в stderr

range и xrange

Python 2:

# range возвращает список (потребляет память)
for i in range(1000000):
    pass  # Создаёт список из 1 млн элементов

# xrange возвращает итератор (экономит память)
for i in xrange(1000000):
    pass  # Генерирует значения на лету

Python 3:

# range работает как старый xrange (возвращает итератор)
for i in range(1000000):
    pass  # Ленивая генерация

# xrange больше нет
xrange(10)  # NameError: name 'xrange' is not defined

input и raw_input

Python 2:

# raw_input возвращает строку
name = raw_input("Enter name: ")  # type: str (bytes)

# input вычисляет выражение Python (опасно!)
result = input("Enter number: ")  # Вычисляет код
# Если пользователь введёт 2+2, вернёт 4

Python 3:

# input возвращает строку (как raw_input в Python 2)
name = input("Enter name: ")  # type: str (unicode)

# raw_input больше нет
# eval() для вычисления выражений (явно)
result = eval(input("Enter number: "))

Исключения

Python 2:

# Старый синтаксис
try:
    risky_operation()
except IOError, e:
    print "Error:", e
except (ValueError, TypeError), e:
    print "Type error:", e
except Exception, e:
    print "Exception:", e
finally:
    cleanup()

# raise с тремя аргументами
raise IOError, "message", traceback

Python 3:

# Новый синтаксис
try:
    risky_operation()
except IOError as e:
    print("Error:", e)
except (ValueError, TypeError) as e:
    print("Type error:", e)
except Exception as e:
    print("Exception:", e)
finally:
    cleanup()

# raise с одним аргументом (или цепочкой)
raise IOError("message") from original_error
raise IOError("message")  # Заменяет старый traceback

Dict методы

Python 2:

d = {"a": 1, "b": 2}

# dict.keys(), dict.values(), dict.items() возвращают список
keys = d.keys()  # type: list
values = d.values()  # type: list
items = d.items()  # type: list

# Итераторные версии
keys = d.iterkeys()  # type: iterator
values = d.itervalues()  # type: iterator
items = d.iteritems()  # type: iterator

# has_key
if d.has_key("a"):
    pass

Python 3:

d = {"a": 1, "b": 2}

# dict.keys(), dict.values(), dict.items() возвращают view
keys = d.keys()  # type: dict_keys (view)
values = d.values()  # type: dict_values (view)
items = d.items()  # type: dict_items (view)

# Итераторные версии удалены (keys/values/items уже ленивые)
# iterkeys, itervalues, iteritems больше нет

# Используй in вместо has_key
if "a" in d:
    pass

Наследование

Python 2:

# Нужно наследоваться от object для new-style классов
class OldStyle:
    pass

class NewStyle(object):
    pass

obj = OldStyle()
print type(obj)  # <type 'instance'>

obj2 = NewStyle()
print type(obj2)  # <class '__main__.NewStyle'>

# super() сложнее
class Child(NewStyle):
    def __init__(self):
        super(Child, self).__init__()

Python 3:

# Все классы наследуются от object по умолчанию
class MyClass:
    pass

# Все классы — new-style
obj = MyClass()
print(type(obj))  # <class '__main__.MyClass'>

# super() упрощен
class Child(MyClass):
    def __init__(self):
        super().__init__()

Целые числа

Python 2:

# Два типа целых: int и long
a = 10  # type: int
b = 10L  # type: long (очень больших чисел)

# Переполнение int превращается в long
big = 10**100  # type: long (автоматически)

# Деление может перелиться
result = 999999999999999999999999999999 / 2  # Может быть неточно

Python 3:

# Один тип целых: int (с произвольной точностью)
a = 10  # type: int
b = 10  # type: int (нет L)

# Всегда big integers
big = 10**100  # type: int (произвольная точность)

# Деление всегда точное
result = 999999999999999999999999999999 / 2  # Точно

Функции и параметры

Python 2:

# Позиционные параметры после *args
def func(a, *args, b=10):
    pass
# SyntaxError!

# Нужно использовать **kwargs
def func(a, *args, **kwargs):
    b = kwargs.get('b', 10)

Python 3:

# Keyword-only параметры после *args
def func(a, *args, b=10):
    pass

func(1, 2, 3, b=20)  # Работает

# Позиционные параметры можно заморозить
def func(a, /, b, *, c):
    pass
# a — позиционный только
# b — позиционный или keyword
# c — keyword только

Генераторы и comprehensions

Python 2:

# List comprehension конфликтует с переменной в области видимости
result = [x for x in range(10)]
print(x)  # x всё ещё определена! (9)

# Dict comprehension работает
d = {x: x**2 for x in range(5)}

# Set comprehension недоступен (используй set())
s = set(x for x in range(5))

Python 3:

# List comprehension имеет свою область видимости
result = [x for x in range(10)]
print(x)  # NameError: name 'x' is not defined

# Dict comprehension
d = {x: x**2 for x in range(5)}

# Set comprehension
s = {x for x in range(5)}

Import система

Python 2:

# Относительные импорты неоднозначны
from mymodule import something  # Может быть локальный или встроенный

# Параллельные импорты
import ConfigParser  # Встроенный модуль
import MySQLdb  # Сторонний

Python 3:

# Явные относительные импорты
from . import something  # Из текущего пакета
from .. import something  # Из родительского пакета
from mymodule import something  # Абсолютный импорт

# Стандартизированные имена
import configparser  # Все встроенные модули в нижнем регистре
import MySQLdb  # Сторонние могут быть в любом регистре

Практическое значение

Если нужно поддерживать старый Python 2 код:

# Используй future imports для совместимости
from __future__ import print_function
from __future__ import unicode_literals
from __future__ import division

print("hello")  # Работает как в Python 3
result = 5 / 2  # 2.5
s = "hello"  # type: unicode

Заключение

Пython 2 был революционным на своё время, но Python 3 решает множество проблем:

  • Unicode по умолчанию — правильная обработка текста
  • Консистентные типы — нет путаницы int/long
  • Лучшая производительность — оптимизации для Python 3
  • Современные возможности — async/await, type hints и т.д.

Миграция на Python 3 критична для новых проектов. Python 2 полностью вышел из поддержки и представляет уязвимости безопасности.

Какие особенности и ограничения были в Python 2 по сравнению с более поздними версиями? | PrepBro