Diferenças entre o Python 2 e o Python 3

Em breve, mais cedo ou mais tarde, teremos que migrar uma aplicação feita em Python 2.x para Python 3, não tem jeito é o nosso destino e porque migrar?

Como está escrito na wiki oficial do Python:
Python 2.7 é legado e o Python 3 é o presente e o futuro da linguagem.

Python 3 foi lançado em 2008, já a versão final do Python 2, a versão 2.7, saiu por volta de 2010, mas já com a decisão que a família 2.x não teria grandes releases. E desde então a versão 3.x vem sendo melhorada e conta com versões estáveis desde então, como por exemplo as versões 3.3 em 2012, 3.4 em 2014 e 3.5 em 2015.

Uma das primeiras mudanças que vemos no Python 3 é na função print, que agora realmente é uma função:

Python 2:

Python 3:

Podemos também usar alguns argumentos novos na função print como por exemplo o end e o sep:

Divisão entre números inteiros mudou um pouco:

No Python 2.x a divisão entre 3 / 2 sempre retorna 1, mas no Python 3 o resultado é 1,5 (que bom né, rs), porque agora a divisão não depende mais do tipo do denominador e do numerador.

Se for necessário utilizar o comportamento antigo utilize duas barras, assim: 3 // 2

True e False agora são palavras reservadas:

No Python 2 podiamos fazer algumas coisas estranhas como:

No Python 3 finalmente isso não é mais possível:

Raising exceptions:

No Python 2.x podiamos usar a velha e nova sintaxe. No Python 3 podemos usar apenas a nova:
Python 2:

Python 3:
Só assim:

Manipulando exceções:

No Python 3 temos que usar obrigatoriamente a palavra chave “as
Python 2:

Python 3:

Unpacking avançado:

Agora podemos fazer coisas do tipo:

“keyword-only” arguments:

Com a função acima em mente vamos imaginar que você precisa que o parâmetro option seja usado da forma como está no contrato da função, ou seja, deve ser passado como no exemplo abaixo:

>>> fn(1, 2, option=False)
e nunca
>>> fn(1, 2, 3) # -> desse modo, o parâmetro option teria o valor 3 e não é o que queremos.

Felizmente no Python 3 isso é possivel, basta adicionar o argumento de quantidade indefinida de parâmetros posicionais, aqui representado por *args, como no exemplo abaixo:

E assim dessa forma podemos chamar a função fn desse jeito:
>>> fn(1, 2, 3): # -> o parâmetro de valor 3 foi enviado para o argumento *args.
E o parâmetro option continua com o valor True.

Poderiamos utilizar dessa forma, que também funcionaria:
>>> fn(1, 2, 3, 4, option=False) # -> os parâmetro 3 e 4 foram enviados para o argumento *args.

Tudo agora é iterator

Se você fizer no Python 2.x:

Tem grandes chances do seu computador travar, bem travado. Por que? Porque a função range() tenta alocar neste caso um espaço na memória com 100000000 posições, detonando a memória da máquina. Já no Python 3 isso não acontece porque a função range() retorna uma espécie de iterator que vai liberando a memória a cada loop.
Com isso a função xrange() do Python 2.x foi eleminada sem dó, pois o range() agora faz o papel que ela fazia.
Por isso em Python 3, range, zip, map, list, etc, são todos iterators.
Se você precisa de uma lista basta fazer isto: list(range(10))

Comparar tudo com tudo, não pode mais:

Python 2:

something_is_worng.jpg

No Python 3 isso não pode mais, melhor assim né:

O método .next() dos iterators foi para o /dev/null

No Python 2.x podemos utilizar a função built-in next() e também o método .next() de um iterator. Já no Python 3 isso mudou, ficamos apenas com a função next().
Python 2:

Python 3:

O método has_key(), aquele dos dicionários, não existe mais:

Em Python 2, poderia ser feito:

No Python 3, temos que usar o operado in:

Variáveis de controle em List comprehensions não mais afetam o escopo a sua volta:

Python 2:

Python 3:

Finalmente o tipo enumerado faz parte da biblioteca padrão do Python:

No Python 3.4, agora temos:

O raw_input não existe mais:

No Python 2.x temos o raw_input e o input para fazer a leitura dos dados do teclado. O raw_input lê strings em geral e o input lê apenas números.
No python 3 existe apenas o input que lê tudo como strings, então se você precisa de uma entrada numérica basta converter assim:

Nome de variáveis unicode:

Valeuuuu, :)

Referências que usei para criar este post:
https://docs.python.org/3/whatsnew/3.0.html
https://asmeurer.github.io/python3-presentation/slides.html#1
https://pythonhelp.wordpress.com/2013/09/01/o-que-mudou-no-python-3/
http://sebastianraschka.com/Articles/2014_python_2_3_key_diff.html#future_module

  • Sergio Campos

    O método next foi renomeado pra __next__ ;)

    • Mateus Pádua

      Valeu Sergio pela explicação, vou atualizar o post com essa nota.

  • Pedro Jefferson

    Uma ferramenta que me ajudou bastante na hora de migrar codigo 2.x para 3.x é o 2to3.

    https://docs.python.org/2/library/2to3.html

    • Mateus Pádua

      Pedro, obrigado pela dica, abraços

  • Josue Freitas

    Excelente artigo!

    • Mateus Pádua

      Obrigado Josue

  • Henrique

    Muito bom!!
    Não sabia que existia duas versões e suas diferenças, nunca programei com Python, mas pretendo utilizar para melhorar o processamento de dados com Spark.

    Posso concluir então que quem vai iniciar no mundo Python é recomendável a versão 3.x?
    Abs

    • Mateus Pádua

      Olá Henrique, recomendo sim começar pelo Python 3, pois o Python 2 será extinto daqui três anos. https://pythonclock.org/ . Value