Несовместимость при переходе с Python 2 на Python 3

Введение

Примеры

  • 91

    Печать заявления против функции печати

    В Python 2, print является утверждение:

    печать "Hello World" печать # печать новой строки печать "No newline", # добавление запятой для удаления новой строки print >> sys.stderr, "Error" # печать в stderr print ("hello") # печать "hello", так как ("hello") == "hello" print () # печать пустого кортежа "()" print 1, 2, 3 # печать аргументов, разделенных пробелами: "1 2 3" печать (1, 2, 3) # печать кортеж "(1, 2, 3)"

    В Python 3, print() является функцией, с аргументами ключевого слова для общего использования:

    print "Hello World" # SyntaxError print ("Hello World") print () # печать новой строки (необходимо использовать круглые скобки) print ("Без новой строки", end = "") # end указывает, что добавить (по умолчанию для новой строки) print («Ошибка», file = sys.stderr) # файл задает выходной буфер печати («Запятая», «разделенный», «вывод», sep = «,») # sep указывает разделитель печати («A», «B» "," C ", sep =" ") # пустая строка для sep: печатает как ABC print (" Flush this ", flush = True) # очищает выходной буфер, добавленный в Python 3.3 print (1, 2, 3) # выводите разделенные пробелом аргументы: «1 2 3» print ((1, 2, 3)) # print tuple «(1, 2, 3)»

    Функция печати имеет следующие параметры:

     print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
    
     

    sep является то , что отделяет объекты , которые проходят на печать. Например:

     print('foo', 'bar', sep='~') # out: foo~bar
    print('foo', 'bar', sep='.') # out: foo.bar
    
     

    end является то , что конец оператора печати следует. Например:

     print('foo', 'bar', end='!') # out: foo bar!
    
     

    Печать снова после отсутствия новой строки , закончившейся оператор печати будет печатать на ту же строку:

     print('foo', end='~')
    print('bar')
    # out: foo~bar
    
     

    Примечание: Для будущей совместимости print функция также доступна в Python 2.6 года; однако он не может быть использован , если парсинг print заявления не отключен с

     from __future__ import print_function
    
     

    Эта функция имеет точно такое же формат , как Python 3 - х, за исключением того, что ему не хватает flush параметра.

    См PEP 3105 для обоснования.

  • 123

    Строки: байты против юникода

    В Python 2 есть два варианта строки: сделанные из байт с типом ( str ) и изготовленные из текста с типом ( unicode ).

    В Python 2, объект типа str всегда является последовательность байт, но обычно используется как для текстовых и двоичных данных.

    Строковый литерал интерпретируется как байтовая строка.

     s = 'Cafe'    # type(s) == str
    
     

    Есть два исключения: Вы можете определить Unicode (текст) буквальный явно предваряя литерал u :

     s = u'Café'   # type(s) == unicode
    b = 'Lorem ipsum'  # type(b) == str
    
     

    В качестве альтернативы вы можете указать, что строковые литералы всего модуля должны создавать литералы Unicode (текст):

     from __future__ import unicode_literals
    
    s = 'Café'   # type(s) == unicode
    b = 'Lorem ipsum'  # type(b) == unicode
    
     

    Чтобы проверить, является ли ваша переменная строкой (Unicode или байтовой строкой), вы можете использовать:

     isinstance(s, basestring)
    
     

    В Python 3, str тип является типом текста Unicode.

     s = 'Cafe'           # type(s) == str
    s = 'Café'           # type(s) == str (note the accented trailing e)
    
     

    Кроме того, Python 3 добавил bytes объекта , подходящий для бинарных «сгустков» или запись кодирования файлов , не зависящее. Чтобы создать объект байт, вы можете префикс b в строку буквальной или вызвать струны encode метод:

     # Or, if you really need a byte string:
    s = b'Cafe'          # type(s) == bytes
    s = 'Café'.encode()  # type(s) == bytes
    
     

    Чтобы проверить, является ли значение строкой, используйте:

     isinstance(s, str)
    
     

    Можно также в качестве префикса строковые литералы с u префиксом для облегчения совместимости между Python 2 и Python 3 кода баз. Так, в Python 3 все строки Unicode по умолчанию, предваряя строковый литерал с u не имеет никакого эффекта:

     u'Cafe' == 'Cafe'
    
     

    Python 2 в сырце Unicode строки префикс ur не поддерживаются, однако:

     >>> ur'Café'
      File "<stdin>", line 1
        ur'Café'
               ^
    SyntaxError: invalid syntax
    
     

    Обратите внимание , что вы должны encode в Python 3 текста ( str объект) , чтобы преобразовать его в bytes представление этого текста. Кодирование по умолчанию этого метода является UTF-8 .

    Вы можете использовать decode задать bytes объект для того, что текст Unicode представляет:

     >>> b.decode()
    'Café'
    
     
    В то время как тип `bytes` существует как в Python 2, так и в 3, тип` unicode` существует только в Python 2. Чтобы использовать неявные строки Unicode в Python 2 в Python 2, добавьте следующее в начало вашего файла кода: из __future__ import unicode_literals print (repr ("hi")) # u'hi ' Другое важное отличие состоит в том, что индексирование байтов в Python 3 приводит к выводу `int`, например: b" abc "[0] == 97 В то время как нарезка размером до одного приводит к объекту длиной 1 байт: b" abc "[ 0: 1] == b "a"

    Кроме того, Python 3 исправляет некоторые необычное поведение с юникода, то есть реверсивные байт строки в Python 2. Например, следующий вопрос будет решен:

     # -*- coding: utf8 -*-
    print("Hi, my name is Łukasz Langa.")
    print(u"Hi, my name is Łukasz Langa."[::-1])
    print("Hi, my name is Łukasz Langa."[::-1])
    
    # Output in Python 2
    # Hi, my name is Łukasz Langa.
    # .agnaL zsakuŁ si eman ym ,iH
    # .agnaL zsaku�� si eman ym ,iH
    
    # Output in Python 3
    # Hi, my name is Łukasz Langa.
    # .agnaL zsakuŁ si eman ym ,iH
    # .agnaL zsakuŁ si eman ym ,iH 
  • 336

    Целочисленное деление

    Стандартный символ деления ( / ) работает по- разному в Python 3 и Python 2 , когда применяется к целым числам.

    При делении целого числа на другое целое число в Python 3, операция деления x / y представляет собой истинное деление (использует __truediv__ метод) и дает результат с плавающей точкой. В том же время, та же операция в Python 2 представляет собой классическое деление , которая округляется результат вниз к отрицательной бесконечности (также известной как взятие на поле).

    Например:

    Код Выход Python 2 Выход Python 3
    3 / 2 1 1,5
    2 / 3 0 0,6666666666666666
    -3 / 2 -2 -1,5

    Поведение округление- в сторону ноль был устаревшим в Python 2.2 , но остается в Python 2.7 для обратной совместимости и был удален в Python 3.

    Примечание: Для того, чтобы получить результат с плавающей точкой в Python 2 (без пола округления) мы можем указать один из операндов с десятичной точкой. Выше пример 2/3 , который дает 0 в Python 2 , должны быть использованы в качестве 2 / 3.0 или 2.0 / 3 или 2.0/3.0 , чтобы получить 0.6666666666666666

    Код Выход Python 2 Выход Python 3
    3.0 / 2.0 1,5 1,5
    2 / 3.0 0,6666666666666666 0,6666666666666666
    -3.0 / 2 -1,5 -1,5

    Существует также оператор пола деления ( // ), который работает так же , как в обеих версиях: она округляется до ближайшего целого числа. (хотя поплавок возвращается при использовании поплавков) В обоих версиях // оператор карты для __floordiv__ .

    Код Выход Python 2 Выход Python 3
    3 // 2 1 1
    2 // 3 0 0
    -3 // 2 -2 -2
    3.0 // 2.0 1,0 1,0
    2.0 // 3 0.0 0.0
    -3 // 2.0 -2,0 -2,0

    Можно явно обеспечивать истинное деление или деление пола с использованием собственных функций в operator модуле:

     from operator import truediv, floordiv
    assert truediv(10, 8) == 1.25            # equivalent to `/` in Python 3
    assert floordiv(10, 8) == 1              # equivalent to `//`
    
     

    Хотя операторные функции для каждого деления понятны и явны, они могут быть утомительными. Изменение поведения / часто будет предпочтительным оператором. Обычная практика является устранение типичного поведения деления пути добавления from __future__ import division в качестве первого оператора в каждом модуле:

     # needs to be the first statement in a module
    from __future__ import division
    
     
    Код Выход Python 2 Выход Python 3
    3 / 2 1,5 1,5
    2 / 3 0,6666666666666666 0,6666666666666666
    -3 / 2 -1,5 -1,5

    from __future__ import division гарантирует , что / оператор представляет истинное деление и только в модулях , которые содержат __future__ импорт, так что нет никаких веских причин не позволяет ей во всех новых модулях.

    Примечание: Некоторые другие языки программирования используют округление к нулю (усечение) , а не округление вниз к отрицательной бесконечности , как это делает Python (т.е. на этих языках -3 / 2 == -1 ). Такое поведение может создать путаницу при переносе или сравнении кода.


    Обратите внимание на флоат операндами: В качестве альтернативы from __future__ import division , можно было бы использовать символ обычное разделение / и гарантировать , что по крайней мере один из операндов с плавающей точкой: 3 / 2.0 == 1.5 . Однако это можно считать плохой практикой. Это слишком просто , чтобы написать average = sum(items) / len(items) и забудьте бросить один из аргументов , чтобы плавать. Кроме того, такие случаи часто могут уйти от внимания во время тестирования, например, если вы тестируете на массив , содержащий float с , но получить массив int s в производстве. Кроме того, если тот же код используется в Python 3, программа, планирующая 3 / 2 == 1 , чтобы быть правдой не будет работать правильно.

    См PEP 238 для более детального обоснования , почему оператор деления был изменен в Python 3 и почему деление старого стиля следует избегать.


    Смотрите Simple Math тему больше о разделении.

  • 8

    Уменьшить больше не является встроенным

    В Python 2, reduce доступен либо в виде встроенной функции или из functools пакета (версия 2.6) и далее, в то время как в Python 3 reduce доступна только из functools . Однако синтаксис для reduce в обоих python2 и Python3 то же самое , и это reduce(function_to_reduce, list_to_reduce) .

    В качестве примера рассмотрим уменьшение списка до одного значения путем деления каждого из соседних чисел. Здесь мы используем truediv функции от operator библиотеки.

    В Python 2.x это так же просто, как:

    >>> my_list = [1, 2, 3, 4, 5] >>> оператор импорта >>> Reduce (operator.truediv, my_list) 0,008333333333333333

    В Python 3.x пример становится немного сложнее:

    >>> my_list = [1, 2, 3, 4, 5] >>> оператор импорта, functools >>> functools.reduce (operator.truediv, my_list) 0.008333333333333333

    Мы также можем использовать from functools import reduce , чтобы избежать вызова reduce с именем пространства имен.

  • 46

    Различия между функциями range и xrange

    В Python 2, range функция возвращает список , а xrange создает специальный xrange объект, который является непреложной последовательностью, которая в отличие от других встроенных типов последовательностей, не поддерживает нарезку и не имеет ни index , ни count методы:

    print (диапазон (1, 10)) # Out: [1, 2, 3, 4, 5, 6, 7, 8, 9] print (isinstance (диапазон (1, 10), список)) # Out: True print (xrange (1, 10)) # Out: xrange (1, 10) print (isinstance (xrange (1, 10), xrange)) # Out: True

    В Python 3, xrange был расширен до range последовательности, которая , таким образом , в настоящее время создает range объекта. Там нет xrange типа:

    print (диапазон (1, 10)) # Out: диапазон (1, 10) print (isinstance (диапазон (1, 10), диапазон)) # Out: True # print (xrange (1, 10)) # Выход будет be: #Traceback (последний вызов был последним): # File " ", строка 1, в #NameError: имя 'xrange' не определено

    Кроме того, поскольку Python 3.2, range также поддерживает нарезку, index и count :

    print (диапазон (1, 10) [3: 7]) # Out: диапазон (3, 7) print (диапазон (1, 10) .count (5)) # Out: 1 отпечаток (диапазон (1, 10). index (7)) # Out: 6

    Преимущество использования специального типа последовательности вместо списка состоит в том, что интерпретатору не нужно выделять память для списка и заполнять его:

    # range (10000000000000000) # Вывод будет: # Traceback (последний вызов был последним): # File " ", строка 1, в # MemoryError print (xrange (100000000000000000)) # Out: xrange (100000000000000000)

    Поскольку последнее поведение , как правило , желательно, первый был удален в Python 3. Если вы все еще хотите иметь список в Python 3, вы можете просто использовать list() конструктор на range объекта:

    print (list (range (1, 10))) # Out: [1, 2, 3, 4, 5, 6, 7, 8, 9]

    Совместимость

    Для того , чтобы обеспечить совместимость между обоими 2.x Python и версии 3.x на Python, вы можете использовать builtins функции модуля из внешнего пакета future для достижения как вперед-и назад Совместимость-Совместимость:

    # прямая совместимость из встроенного диапазона импорта для i в диапазоне (10 ** 8): проход # обратно совместимый из past.builtins import xrange для i в xrange (10 ** 8): pass

    range в future библиотеке поддерживает нарезку, index и count во всех версиях Python, так же , как встроенный метод на Python 3.2+.

  • 147

    Распаковка товаров

    В Python 3 вы можете распаковать итерируемое, не зная точного количества элементов в нем, и даже иметь переменную, содержащую конец итерируемого. Для этого вы предоставляете переменную, которая может собирать список значений. Это делается путем помещения звездочки перед именем. Например, распаковка list :

     first, second, *tail, last = [1, 2, 3, 4, 5]
    print(first)
    # Out: 1
    print(second)
    # Out: 2
    print(tail)
    # Out: [3, 4]
    print(last)
    # Out: 5
    
     

    Примечание: При использовании *variable синтаксиса, то variable всегда будет список, даже если исходный тип не был список. Он может содержать ноль или более элементов в зависимости от количества элементов в исходном списке.

     first, second, *tail, last = [1, 2, 3, 4]
    print(tail)
    # Out: [3]
    
    first, second, *tail, last = [1, 2, 3]
    print(tail)
    # Out: []
    print(last)
    # Out: 3
    
     

    Аналогичным образом , распаковка str :

     begin, *tail = "Hello"
    print(begin)
    # Out: 'H'
    print(tail)
    # Out: ['e', 'l', 'l', 'o']
    
     

    Пример распаковки date ; _ Используется в этом примере в качестве переменной (холостой мы заинтересованы только в year стоимости):

     person = ('John', 'Doe', (10, 16, 2016))
    *_, (*_, year_of_birth) = person
    print(year_of_birth)
    # Out: 2016
    
     

    Стоит отметить , что, так как * съедает переменное число элементов, вы не можете иметь два * s для той же итерации в назначении - это не будет знать , сколько элементов идти в первую распаковку, и сколько во втором :

     *head, *tail = [1, 2]
    # Out: SyntaxError: two starred expressions in assignment
    
    
     

    До сих пор мы обсуждали распаковку в назначениях. * И ** были распространены в Python 3.5 . Теперь возможно иметь несколько операций распаковки в одном выражении:

     {*range(4), 4, *(5, 6, 7)}
    # Out: {0, 1, 2, 3, 4, 5, 6, 7}
    
     

    Также возможно распаковать итерацию в аргументы функции:

     iterable = [1, 2, 3, 4, 5]
    print(iterable)
    # Out: [1, 2, 3, 4, 5]
    print(*iterable)
    # Out: 1 2 3 4 5
    
     

    Распаковка словаря использует две смежные звезда ** ( PEP 448 ):

     tail = {'y': 2, 'z': 3}
    {'x': 1, **tail}
     # Out: {'x': 1, 'y': 2, 'z': 3}
    
     

    Это позволяет как переопределять старые значения, так и объединять словари.

     dict1 = {'x': 1, 'y': 1}
    dict2 = {'y': 2, 'z': 3}
    {**dict1, **dict2}
    # Out: {'x': 1, 'y': 2, 'z': 3}
    
     

    Python 3 убрал распаковку кортежей в функциях. Следовательно, следующее не работает в Python 3

     # Works in Python 2, but syntax error in Python 3:
    map(lambda (x, y): x + y, zip(range(5), range(5)))
    # Same is true for non-lambdas:
    def example((x, y)):
        pass
    
    # Works in both Python 2 and Python 3:
    map(lambda x: x[0] + x[1], zip(range(5), range(5)))
    # And non-lambdas, too:
    def working_example(x_y):
        x, y = x_y
        pass
    
     

    См PEP 3113 для детального обоснования.

  • 30

    Поднятие и обработка исключений

    Это синтаксис Python 2, обратите внимание на запятые , на raise и , except линий:

    try: поднять IOError, «ошибка ввода / вывода», кроме IOError, exc: print exc

    В Python 3, , синтаксис отбрасывается и заменяется скобкой и в as ключевого слова:

     try:
        raise IOError("input/output error")
    except IOError as exc:
        print(exc)
    
    
     

    Для обратной совместимости синтаксис Python 3 также доступен в Python 2.6 и далее, поэтому его следует использовать для всего нового кода, который не должен быть совместимым с предыдущими версиями.


    В Python 3 также добавлена ​​[цепочка исключений] (https://codecamp.ru/documentation/python/1788/exceptions/5533/chain-exceptions-with-raise-from#t=201608030127064987456), в которой вы можете указать, что какое-то другое исключение была * причиной * для этого исключения. Например, попробуйте: file = open ('database.db'), за исключением FileNotFoundError как e: повысить DatabaseError ('Cannot open {}') от e Исключение, вызванное в операторе `кроме`, имеет тип` DatabaseError`, но оригинал исключение помечается как атрибут `__cause__` этого исключения. Когда отображается трассировка, оригинальное исключение также будет отображаться в трассировке:
     Traceback (most recent call last):
      File "<stdin>", line 2, in <module>
    FileNotFoundError
    
    The above exception was the direct cause of the following exception:
    
    Traceback (most recent call last):
      File "<stdin>", line 4, in <module>
    DatabaseError('Cannot open database.db')
    
     

    Если бросить в за except блока без явного логического вывода:

     try:
        file = open('database.db')
    except FileNotFoundError as e:
        raise DatabaseError('Cannot open {}')
    
     

    Обратная связь

     Traceback (most recent call last):
      File "<stdin>", line 2, in <module>
    FileNotFoundError
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "<stdin>", line 4, in <module>
    DatabaseError('Cannot open database.db')
     
    Ни один из них не поддерживается в Python 2.x; исходное исключение и его трассировка будут потеряны, если в блоке исключений возникнет другое исключение. Для совместимости можно использовать следующий код: import sys import traceback try: funcWithError () кроме: sys_vers = getattr (sys, 'version_info', (0,)), если sys_vers <(3, 0): traceback.print_exc () повышение Исключение («новое исключение») Чтобы «забыть» ранее сгенерированное исключение, используйте команду «повысить из None». Try: file = open ('database.db'), за исключением FileNotFoundError, как e: Повышение DatabaseError ('Cannot open {}') из None. Теперь трассировка будет просто
     Traceback (most recent call last):
      File "<stdin>", line 4, in <module>
    DatabaseError('Cannot open database.db')
    
     

    Или для того , чтобы сделать его совместимым как с Python 2 и 3 , вы можете использовать шесть пакетов, так:

     import six
    try:
        file = open('database.db')
    except FileNotFoundError as e:
        six.raise_from(DatabaseError('Cannot open {}'), None)
    
     
  • 12

    Метод .next () на итераторах переименован

    В Python 2, итератор может перемещаться с помощью метода , называемого next на самом итератора:

    `` `g = (i для i в диапазоне (0, 3)) g.next () # Выход 0 0 g.next () # Выход 1 g.next () # Выход 2` ``

    В Python 3, .next метод был переименован в .__next__ , признавая свою «волшебную» роль, поэтому вызов .next возбудит AttributeError . Правильный способ доступа к этой функции как в Python 2 и Python 3, чтобы вызвать next функцию с итератором в качестве аргумента.

    `` `g = (i для i в диапазоне (0, 3)) next (g) # Выход 0 0 next (g) # Выход 1 next (g) # Выход 2` ``

    Этот код переносится между версиями от 2.6 до текущих версий.

  • 17

    Сравнение разных типов

    Объекты разных типов можно сравнивать. Результаты произвольны, но последовательны. Они упорядочены так, что `None` меньше, чем что-либо другое, числовые типы меньше, чем нечисловые типы, а все остальное упорядочено лексикографически по типу. Таким образом, `int` меньше, чем` str`, а `tuple` больше, чем` list`: [1, 2]> 'foo' # Out: False (1, 2)> 'foo' # Out : True [1, 2]> (1, 2) # Out: False 100 <[1, 'x'] <'xyz' <(1, 'x') # Out: True Первоначально это было сделано, поэтому список смешанные типы могут быть отсортированы, и объекты будут сгруппированы по типу: l = [7, 'x', (1, 2), [5, 6], 5, 8.0, 'y', 1.2, [7, 8] , 'z'] отсортировано (l) # Out: [1.2, 5, 7, 8.0, [5, 6], [7, 8], 'x', 'y', 'z', (1, 2) ] Возникает исключение при сравнении разных (не числовых) типов: 1 <1.5 # Out: True [1, 2]> 'foo' # TypeError: неупорядоченные типы: list ()> str () (1, 2)> ' foo '# TypeError: неустранимые типы: tuple ()> str () [1, 2]> (1, 2) # TypeError: неустранимые типы: list ()> tuple ()

    Чтобы отсортировать смешанные списки в Python 3 по типам и добиться совместимости между версиями, вы должны предоставить ключ для отсортированной функции:

     >>> list = [1, 'hello', [3, 4], {'python': 2}, 'stackoverflow', 8, {'python': 3}, [5, 6]]
    >>> sorted(list, key=str)
    # Out: [1, 8, [3, 4], [5, 6], 'hello', 'stackoverflow', {'python': 2}, {'python': 3}]
    
     

    Использование str как key функция временно преобразует каждый элемент строки только для целей сравнения. Затем он видит строковое представление начинающимся с [ , ' , { или 0-9 , и это возможность отсортировать те (и все последующие).

  • 23

    Пользовательский ввод

    В Python 2, пользовательский ввод принимается с использованием raw_input функции,

    user_input = raw_input ()

    В то время как в Python 3 пользовательского ввода принимается с помощью input функции.

    user_input = input ()

    В Python 2, input функция принимает входной сигнал и интерпретировать его. Хотя это может быть полезным, он имеет несколько соображений безопасности , и был удален в Python 3. Чтобы получить доступ к тому же функциональности, eval(input()) может быть использован.

    Чтобы сохранить переносимость скрипта между двумя версиями, вы можете поместить приведенный ниже код в верхнюю часть скрипта Python:

     try:
        input = raw_input
    except NameError:
        pass 
  • 1

    Изменения в методе словаря

    В Python 3, многие из словарных методов сильно отличаются в поведении от Python 2, и многие из них были удалены , а также: has_key , iter* и view* ушли в прошлое. Вместо d.has_key(key) , который уже давно устаревшие, теперь нужно использовать key in d .

    В Python 2, словарные методы keys , values и items возвращают списки. В Python 3 они возвращаются просматривать объекты , а не ; объекты представления не являются итераторами, и они отличаются от них двумя способами, а именно:

    • они имеют размер (можно использовать len функцию на них)
    • они могут повторяться много раз

    Кроме того, как и в случае с итераторами, изменения в словаре отражаются в объектах представления.

    Python 2.7 перенес эти методы из Python 3; они доступны как viewkeys , viewvalues и viewitems . Чтобы преобразовать код Python 2 в код Python 3, соответствующие формы:

    • d.keys() , d.values() и d.items() из Python 2 должен быть изменен list(d.keys()) , list(d.values()) и list(d.items())
    • d.iterkeys() , d.itervalues() и d.iteritems() должен быть изменен на iter(d.keys()) , или даже лучше, iter(d) ; iter(d.values()) и iter(d.items()) , соответственно ,
    • и , наконец , Python 2.7 метод вызывает d.viewkeys() , d.viewvalues() и d.viewitems() можно заменить d.keys() , d.values() и d.items() .

    Портирование Python 2 код , который перебирает ключи словаря, значения или элементы , а мутирует это иногда бывает сложно. Рассматривать:

     d = {'a': 0, 'b': 1, 'c': 2, '!': 3}
    for key in d.keys():
        if key.isalpha():
            del d[key]
    
     

    Код выглядит так , как будто он будет работать так же в Python 3, но там keys метод возвращает вид объекта, а не список, а если словарные изменения размера в то же время итерации, код Python 3 будет врезаться с RuntimeError: dictionary changed size during iteration . Решение, конечно , правильно писать for key in list(d) .

    Точно так же, просматривать объекты ведут себя по- разному от итераторов: один не может использовать next() на них, и один не может возобновить итерации; вместо этого он перезапустится; если Python 2 код передает возвращаемое значение d.iterkeys() , d.itervalues() или d.iteritems() к способу , который ожидает итератора вместо итератора, то , что должно быть iter(d) , iter(d.values()) или iter(d.items()) в Python 3.

  • 2

    Оператор exec является функцией в Python 3

    В Python 2, exec это заявление, со специальным синтаксисом: exec code [in globals[, locals]]. В Python 3 exec теперь функция: exec(code, [, globals[, locals]]) , а синтаксис Python 2 поднимут SyntaxError .

    В print была изменена с заявления в функцию, __future__ также был добавлен импорт. Однако, не существует from __future__ import exec_function , так как это не требуется: ехес заявления в Python 2 также можно использовать с синтаксисом , который выглядит так же , как exec вызов функции в Python 3. Таким образом , вы можете изменить заявление

     exec 'code'
    exec 'code' in global_vars
    exec 'code' in global_vars, local_vars
    
     

    к формам

     exec('code')
    exec('code', global_vars)
    exec('code', global_vars, local_vars)
    
     

    и последние формы гарантированно будут работать одинаково как в Python 2, так и в Python 3.

  • 0

    Ошибка функции hasattr в Python 2

    В Python 2, когда свойство поднимать ошибку, hasattr будет игнорировать это свойство, возвращая значение False .

     class A(object):
        @property
        def get(self):
            raise IOError
    
    
    class B(object):
        @property
        def get(self):
            return 'get in b'
    
    a = A()
    b = B()
    
    print 'a hasattr get: ', hasattr(a, 'get')
    # output False in Python 2 (fixed, True in Python 3)
    print 'b hasattr get', hasattr(b, 'get')
    # output True in Python 2 and Python 3
    
     

    Эта ошибка исправлена ​​в Python3. Так что если вы используете Python 2, используйте

     try:
        a.get
    except AttributeError:
        print("no get property!")
    
     

    или использовать getattr вместо

     p = getattr(a, "get", None)
    if p is not None:
        print(p)
    else:
        print("no get property!") 
  • 11

    Переименованные модули

    Несколько модулей в стандартной библиотеке были переименованы:

    Старое имя Новое имя
    _winreg WinREG
    ConfigParser ConfigParser
    copy_reg copyreg
    Очередь очередь
    SocketServer SocketServer
    _markupbase markupbase
    магнезии reprlib
    test.test_support test.support
    Tkinter Tkinter
    tkFileDialog tkinter.filedialog
    urllib / urllib2 urllib, urllib.parse, urllib.error, urllib.response, urllib.request, urllib.robotparser

    Некоторые модули даже были преобразованы из файлов в библиотеки. Возьмите tkinter и urllib сверху в качестве примера.

    Совместимость

    При сохранении совместимости между обоими 2.x и 3.x версий Python, вы можете использовать future внешний пакет для того, чтобы импортировать стандартные пакеты библиотек верхнего уровня с Python 3.x именами на версиях 2.х Python.

  • 3

    Восьмеричные Константы

    В Python 2 восьмеричный литерал может быть определен как

     >>> 0755  # only Python 2 

    Для обеспечения кросс-совместимости используйте

     0o755  # both Python 2 and Python 3 
  • 8

    Все классы являются "классами нового стиля" в Python 3.

    В Python 3.x все классы новых классов; при определении нового класса питона неявно делает его наследовать от object . Таким образом , определяя object в class определение является обязательным:

    класс X: пройти класс Y (объект): пройти

    Оба этих классов в настоящее время содержат object в их mro (метод разрешения заказа):

    >>> X .__ mro__ (__main __. X, объект) >>> Y .__ mro__ (__main __. Y, объект)

    В Python 2.x классы по умолчанию, классы старого стиля; они не неявно наследуют от object . Это приводит к тому , семантике классов различается в зависимости от того, если мы явно добавить object в качестве базового class :

    класс X: пройти класс Y (объект): пройти

    В этом случае, если мы попытаемся вывести __mro__ из Y , аналогичный выход , как в Python 3.x случае появится:

    >>> Y .__ mro__ ( , )

    Это происходит потому , что мы явно сделали Y наследуются от объекта при определении его: class Y(object): pass . Для класса X , который не наследует от объекта , __mro__ атрибут не существует, пытается получить к нему доступ приводит к AttributeError .

    Для того , чтобы обеспечить совместимость между обеими версиями Python классы могут быть определены с object в качестве базового класса:

     class mycls(object):
        """I am fully compatible with Python 2/3"""
    
     

    С другой стороны , если __metaclass__ переменного устанавливаются type в глобальном масштабе, все впоследствии определенные классы в данном модуле, неявно новый стиль без необходимости явно наследоваться от object :

     __metaclass__ = type
    
    class mycls:
        """I am also fully compatible with Python 2/3""" 
  • 10

    Удалены операторы &lt;&gt; и ``, синонимы! = И repr ()

    В Python 2, <> является синонимом != ; аналогично, \`foo\` является синонимом repr(foo) .

     >>> 1 <> 2
    True
    >>> 1 <> 1
    False
    >>> foo = 'hello world'
    >>> repr(foo)
    "'hello world'"
    >>> `foo`
    "'hello world'"
    
     
     >>> 1 <> 2
      File "<stdin>", line 1
        1 <> 2
           ^
    SyntaxError: invalid syntax
    >>> `foo`
      File "<stdin>", line 1
        `foo`
        ^
    SyntaxError: invalid syntax
    
     
  • 2

    кодировать / декодировать в шестнадцатеричный код больше не доступно

     "1deadbeef3".decode('hex')
    # Out: '\x1d\xea\xdb\xee\xf3'
    '\x1d\xea\xdb\xee\xf3'.encode('hex')
    # Out: 1deadbeef3
    
     
     "1deadbeef3".decode('hex')
    # Traceback (most recent call last):
    #   File "<stdin>", line 1, in <module>
    # AttributeError: 'str' object has no attribute 'decode'
    
    b"1deadbeef3".decode('hex')
    # Traceback (most recent call last):
    #   File "<stdin>", line 1, in <module>
    # LookupError: 'hex' is not a text encoding; use codecs.decode() to handle arbitrary codecs
    
    '\x1d\xea\xdb\xee\xf3'.encode('hex')
    # Traceback (most recent call last):
    #   File "<stdin>", line 1, in <module>
    # LookupError: 'hex' is not a text encoding; use codecs.encode() to handle arbitrary codecs
    
    b'\x1d\xea\xdb\xee\xf3'.encode('hex')
    # Traceback (most recent call last):
    #  File "<stdin>", line 1, in <module>
    # AttributeError: 'bytes' object has no attribute 'encode'
    
     

    Однако, как это было предложено в сообщении об ошибке, вы можете использовать codecs модуль для достижения того же результата:

     import codecs
    codecs.decode('1deadbeef4', 'hex')
    # Out: b'\x1d\xea\xdb\xee\xf4'
    codecs.encode(b'\x1d\xea\xdb\xee\xf4', 'hex')
    # Out: b'1deadbeef4'
    
     

    Обратите внимание , что codecs.encode возвращает bytes объекта. Для получения str объект просто decode в ASCII:

     codecs.encode(b'\x1d\xea\xdb\xee\xff', 'hex').decode('ascii')
    # Out: '1deadbeeff'
    
    
     
  • 4

    функция cmp удалена в Python 3

    В Python 3, cmp встроенная функция была удалена, вместе с __cmp__ специальным методом.

    Из документации:

    cmp() функция не следует рассматривать как ушел, и __cmp__() специальный метод больше не поддерживается. Используйте __lt__() для сортировки, __eq__() с __hash__() , а также другими богатыми сравнениями по мере необходимости. (Если вам действительно нужно cmp() функциональные возможности , вы можете использовать выражение (a > b) - (a < b) в качестве эквивалента для cmp(a, b) .)

    Кроме того , все встроенные функции , которые приняты в cmp параметр теперь только принять key ключевое слово только параметр.

    В functools модуле есть также полезная функция cmp_to_key(func) , которая позволяет конвертировать из cmp функции -style к key -style функции:

    Преобразуйте функцию сравнения старого стиля в ключевую функцию. Используется с инструментами , которые принимают ключевые функции (такие , как sorted() , min() , не max() , heapq.nlargest() , heapq.nsmallest() , itertools.groupby() ). Эта функция в основном используется в качестве инструмента перехода для программ, конвертируемых из Python 2, которые поддерживают использование функций сравнения.

  • 27

    Утечка переменных в понимании списка

    x = 'Привет, мир!' гласные = [x для x в 'AEIOU'] print (гласные) # Out: ['A', 'E', 'I', 'O', 'U'] print (x) # Out: 'U' x = 'Привет, мир!' vowels = [x для x в 'AEIOU'] print (гласные) # Out: ['A', 'E', 'I', 'O', 'U'] print (x) # Out: 'привет мир! '

    Как видно из примера, в Python 2 значения x просочилось: она маскируется hello world! и распечатаны U , так как это было последнее значение x , когда цикл закончился.

    Тем не менее, в Python 3 x печатает первоначально определенный hello world! , поскольку локальная переменная из списка понимания не маскирует переменные из окружающей области видимости.

    Кроме того, ни выражения-генераторы (доступные в Python начиная с версии 2.5), ни словарь, ни набор определений (которые были перенесены в Python 2.7 из Python 3) не пропускают переменные в Python 2.

    Обратите внимание, что как в Python 2, так и в Python 3 переменные будут попадать в окружающую область при использовании цикла for:

     x = 'hello world!'
    vowels = []
    for x in 'AEIOU':
        vowels.append(x)
    print(x)
    # Out: 'U' 
  • 6

    карта()

    map() является встроенной , что является полезным для применения функции к элементам итератора. В Python 2, map возвращает список. В Python 3, map возвращает объект карты, который является генератором.

     # Python 2.X
    >>> map(str, [1, 2, 3, 4, 5])
    ['1', '2', '3', '4', '5']
    >>> type(_)
    >>> <class 'list'>
    
    # Python 3.X
    >>> map(str, [1, 2, 3, 4, 5])
    <map object at 0x*>
    >>> type(_)
    <class 'map'>
    
    # We need to apply map again because we "consumed" the previous map....
    >>> map(str, [1, 2, 3, 4, 5])
    >>> list(_)
    ['1', '2', '3', '4', '5']
    
     

    В Python 2, вы не можете передать None , чтобы служить в качестве функции идентификации. Это больше не работает в Python 3.

     >>> map(None, [0, 1, 2, 3, 0, 4])
    [0, 1, 2, 3, 0, 4]
    
     
     >>> list(map(None, [0, 1, 2, 3, 0, 5]))
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: 'NoneType' object is not callable
    
     

    Кроме того, при прохождении более одного Iterable в качестве аргумента в Python 2, map колодка короткий итерируемая с None ( по аналогии с itertools.izip_longest ). В Python 3 итерация останавливается после самой короткой итерации.

    В Python 2:

     >>> map(None, [1, 2, 3], [1, 2], [1, 2, 3, 4, 5])
    [(1, 1, 1), (2, 2, 2), (3, None, 3), (None, None, 4), (None, None, 5)]
    
     

    В Python 3:

     >>> list(map(lambda x, y, z: (x, y, z), [1, 2, 3], [1, 2], [1, 2, 3, 4, 5]))
    [(1, 1, 1), (2, 2, 2)]
    
    # to obtain the same padding as in Python 2 use zip_longest from itertools
    >>> import itertools
    >>> list(itertools.zip_longest([1, 2, 3], [1, 2], [1, 2, 3, 4, 5]))
    [(1, 1, 1), (2, 2, 2), (3, None, 3), (None, None, 4), (None, None, 5)]
    
     

    Примечание: вместо map рекомендуется использовать списковые, которые Python 2/3 совместим. Замена map(str, [1, 2, 3, 4, 5]) :

     >>> [str(i) for i in [1, 2, 3, 4, 5]]
    ['1', '2', '3', '4', '5'] 
  • 11

    filter (), map () и zip () возвращают итераторы вместо последовательностей

    В Python 2 filter , map и zip встроенные функции возвращают последовательность. map и zip всегда возвращает список , а с filter типа возврата зависит от типа данного параметра:

     >>> s = filter(lambda x: x.isalpha(), 'a1b2c3')
    >>> s
    'abc'
    >>> s = map(lambda x: x * x, [0, 1, 2])
    >>> s
    [0, 1, 4]
    >>> s = zip([0, 1, 2], [3, 4, 5])
    >>> s
    [(0, 3), (1, 4), (2, 5)]
    
     

    В Python 3 filter , map и zip обратный итератор вместо:

     >>> it = filter(lambda x: x.isalpha(), 'a1b2c3')
    >>> it
    <filter object at 0x00000098A55C2518>
    >>> ''.join(it)
    'abc'
    >>> it = map(lambda x: x * x, [0, 1, 2])
    >>> it
    <map object at 0x000000E0763C2D30>
    >>> list(it)
    [0, 1, 4]
    >>> it = zip([0, 1, 2], [3, 4, 5])
    >>> it
    <zip object at 0x000000E0763C52C8>
    >>> list(it)
    [(0, 3), (1, 4), (2, 5)]
    
     

    Так как Python 2 itertools.izip является эквивалентом Python 3 zip izip было удалено на Python 3.

  • 7

    Абсолютный / Относительный Импорт

    В Python 3, PEP 404 изменяет путь импорт не работать с Python 2. Неявного относительный импорта больше не разрешается в упаковках и from ... import * импорт допускается только в коде на уровне модуля.

    Для достижения поведения Python 3 в Python 2:

    • в абсолютном импорт функция может быть включен from __future__ import absolute_import
    • явный относительный импорт рекомендуется вместо неявного относительного импорта

    Для пояснения, в Python 2 модуль может импортировать содержимое другого модуля, расположенного в том же каталоге, следующим образом:

     import foo
    
     

    Обратите внимание , что расположение foo неоднозначно от оператора импорта в одиночку. Этот тип неявного относительного импорта, таким образом , не рекомендуется в пользу явного относительно импорта , которые выглядят следующим образом :

     from .moduleY import spam
    from .moduleY import spam as ham
    from . import moduleY
    from ..subpackage1 import moduleY
    from ..subpackage2.moduleZ import eggs
    from ..moduleA import foo
    from ...package import bar
    from ...sys import path
    
     

    Точка . позволяет явное объявление расположения модуля в дереве каталогов.


    Подробнее об относительном импорте

    Рассмотрим некоторые пользовательские пакет под названием shapes . Структура каталогов выглядит следующим образом:

     shapes
    ├── __init__.py
    |
    ├── circle.py
    |
    ├── square.py
    |
    └── triangle.py
    
     

    circle.py , square.py и triangle.py все импорта util.py в качестве модуля. Как они будут ссылаться на модуль на том же уровне?

      from . import util # use util.PI, util.sq(x), etc
    
     

    ИЛИ ЖЕ

      from .util import * #use PI, sq(x), etc to call functions
    
     

    . используется для относительного импорта того же уровня.

    Теперь рассмотрим альтернативный макет shapes модуля:

     shapes
    ├── __init__.py
    |
    ├── circle
    │   ├── __init__.py
    │   └── circle.py
    |
    ├── square
    │   ├── __init__.py
    │   └── square.py
    |
    ├── triangle
    │   ├── __init__.py
    │   ├── triangle.py
    |
    └── util.py
    
     

    Теперь, как эти 3 класса будут ссылаться на util.py?

      from .. import util # use util.PI, util.sq(x), etc
    
     

    ИЛИ ЖЕ

      from ..util import * # use PI, sq(x), etc to call functions
    
     

    .. используются для относительного импорта родительского уровня. Добавить еще . s с количеством уровней между родителем и ребенком.

  • 4

    Файловый ввод / вывод

    file больше не является встроенным имя в 3.x ( open до сих пор работает).

    Внутренние детали файла ввода / вывода, были перенесены в стандартную библиотеку io - StringIO io модуля, который также является новым домом StringIO :

     import io
    assert io.open is open # the builtin is an alias
    buffer = io.StringIO()
    buffer.write('hello, ') # returns number of characters written
    buffer.write('world!\n')
    buffer.getvalue() # 'hello, world!\n'
    
     

    Режим файла (текст или двоичный файл) теперь определяет тип данных, полученных при чтении файла (и тип, необходимый для записи):

     with open('data.txt') as f:
        first_line = next(f)
        assert type(first_line) is str
    with open('data.bin', 'rb') as f:
        first_kb = f.read(1024)
        assert type(first_kb) is bytes
    
     

    Кодирование для текстовых файлов по умолчанию в любой другой возвращается locale.getpreferredencoding(False) . Чтобы указать кодировку явно, использовать encoding параметра ключевое слово:

     with open('old_japanese_poetry.txt', 'shift_jis') as text:
        haiku = text.read() 
  • 5

    Функция round () прерывает связь и возвращает тип

    круглый () разрыв связи

    В Python 2, используя round() по ряду одинаково близко к двум целым числам возвращают один противоположную сторону от 0. Например:

    раунд (1,5) # ушел: 2,0 раунд (0,5) # ушел: 1,0 раунд (-0,5) # ушел: -1,0 раунд (-1,5) # ушел: -2,0

    В Python 3 однако, round() будет возвращать даже целое число (ака банкиров округления). Например:

    раунд (1.5) # Out: 2 раунд (0.5) # Out: 0 раунд (-0.5) # Out: 0 раунд (-1.5) # Out: -2

    Функция округления () следует за половину даже округление стратегия , которая округляет на полпути числа до ближайшего целого числа даже (например, round(2.5) теперь возвращает 2 , а не 3,0).

    По ссылке в Википедии , это также известные как беспристрастное округление, сходящееся округление, округление статистиков, голландское округление гауссового округления или нечетных даже округление.

    Половина даже округления является частью стандарта IEEE 754 стандарта , и это также по умолчанию режим округления в .NET Microsoft.

    Эта стратегия округления уменьшает общую ошибку округления. Поскольку в среднем количество округляемых чисел совпадает с количеством округленных чисел, ошибки округления отменяются. Другие методы округления, как правило, имеют тенденцию к смещению в сторону увеличения или уменьшения средней ошибки.


    round () тип возврата

    round() функция возвращает float типа в Python 2.7

    раунд (4.8) # 5.0

    Начиная с Python 3.0, если второй аргумент (число цифр) опущен, то он возвращает int .

    раунд (4.8) # 5
  • 26

    Правда, Ложь и Нет

    В Python 2, True , False и None встроенные константы. Это означает, что их можно переназначить. True, False = False, True True # False False # True

    Вы не можете сделать это с None , так как Python 2.4. Нет = Нет # Синтаксическая ошибка: невозможно назначить Нет

    В Python 3, True , False , и None не в настоящее время ключевые слова. True, False = False, True # SyntaxError: невозможно назначить ключевое слово

     None = None  # SyntaxError: can't assign to keyword
     
  • 3

    Возвращаемое значение при записи в файл объекта

    В Python 2, писать непосредственно в дескриптор файла возвращает None :

    hi = sys.stdout.write ('hello world \ n') # Out: hello world type (hi) # Out:

    В Python 3 запись в дескриптор вернет количество символов, записанных при написании текста, и количество байтов, записанных при записи байтов:

    import sys char_count = sys.stdout.write ('hello world ? \ n') # Out: hello world ? char_count # Out: 14 byte_count = sys.stdout.buffer.write (b'hello world \ xf0 \ x9f \ x90 \ x8d \ n ') # Out: привет мир ? byte_count # Out: 17
  • 10

    долго против int

    В Python 2, любое целое число больше , чем C ssize_t будет преобразовано в long тип данных, обозначенном L суффикс на буквальном. Например, в 32-битной сборке Python:

     >>> 2**31
    2147483648L
    >>> type(2**31)
    <type 'long'>
    >>> 2**30
    1073741824
    >>> type(2**30)
    <type 'int'>
    >>> 2**31 - 1  # 2**31 is long and long - int is long
    2147483647L
    
     

    Тем не менее, в Python 3, long тип данных был удален; независимо от того , насколько большим числом, оно не будет int .

     2**1024
    # Output: 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
    print(-(2**1024))
    # Output: -179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
    type(2**1024)
    # Output: <class 'int'>
    
     
  • 1

    Класс Boolean Value

    В Python 2, если вы хотите , чтобы определить логическое значение класса самостоятельно, вам нужно реализовать __nonzero__ метод на классе. По умолчанию установлено значение True.

     class MyClass:
        def __nonzero__(self):
            return False
    
    my_instance = MyClass()
    print bool(MyClass)       # True
    print bool(my_instance)   # False
    
     

    В Python 3, __bool__ используется вместо __nonzero__

     class MyClass:
        def __bool__(self):
            return False
    
    my_instance = MyClass()
    print(bool(MyClass))       # True
    print(bool(my_instance))   # False
    
     

Синтаксис

Параметры

Примечания

План темы