Python 2 + 3 = Six

Me

Por que Python 3?

  • Unicode por padrão (adeus UnicodeDecodeError)
  • Mock é uma classe padrão
  • Enum é uma classe padrão
  • AsyncIO
  • SUPORTE AO PYTHON 2 TERMINA EM 2020!

Caminho para o Python 3

  • python -3 [script]
  • 2to3

O que 2to3 arruma

  • print não vai funcionar (é função)
  • iter* não vai funcionar
  • urlib mudou tudo
  • urlparse mudou tudo
  • xrange agora é range e o velho range não existe mais.
  • raw_input mudou

(% para formatar strings retornou, 2to3 não muda para format())

... mas agora o código pode ter ficado incompatível com Python 2...

"Minha infra usa Centos 4 e não tem Python 3 pra Centos!"

"Eu mantenho uma aplicação Python 2.6!"

Six ao resgate!

e seu fiel companheiro __future__!

...mas apenas para aqueles com Python 2.7.

Exemplo (estúpido)

import collections

class Model(object):
    def __init__(self, word):
        self._count = None
        self.word = word
        return

    @property
    def word(self):
        return self._word

    @word.setter
    def word(self, word):
        self._word = word
        self._count = collections.Counter(word)

    @property
    def letters(self):
        return self._count

    def __getitem__(self, pos):
        return self._count[pos]
                        

if __name__ == "__main__":
    word = Model('This is an ex-parrot')
    for letter, count in word.letters.iteritems():
        print letter, count
                        

E Python 3?

class Model(object):

Todas as classes são new style, mas Python 3 não reclama disso.

E Python 3?

for letter, count in word.letters.iteritems():

iteritems() não existe mais no Python 3.

Python 3 tem apenas items(), que funciona de forma diferente no Python 2.

items() no Python 2 gera uma lista inteira nova ao invés de ser um iterador.

E Python 3?

print letter, count

print agora é uma função.

Algumas funcionalidades mudaram (por exemplo, não há mais espaço entre itens).

Compatível entre 2 e 3


class Model(object):
                        

Não precisa fazer nada.

Compatível entre 2 e 3


print letter, count
                        

from __future__ import print_function

[...]

print('{} {}'.format(letter, count))
                        

Compatível entre 2 e 3

(sugestão)


print('{letter} {count}'.format(letter=letter,
                                count=count))
                        

Compatível entre 2 e 3

(sugestão mais melhor ainda)


import six

[...]

six.print_('{letter} {count}'.format(letter=letter,
                                     count=count))
                        

Compatível entre 2 e 3


for letter, count in word.letters.iteritems():
                        

import six

[...]

for letter, count in six.iteritems(word.letters):
                        

🎉 Parabéns! 🎉

Seu código roda em Python 2 E Python 3!

... o código era estúpido mesmo...

Exemplo 2 (real)

import urllib
import urlparse

def add_querystring(url, querystring, value):
    frags = list(urlparse.urlsplit(url))
    query = frags[3]
    query_frags = urlparse.parse_qsl(query)
    query_frags.append((querystring, value))
    frags[3] = urllib.urlencode(query_frags)
    return urlparse.urlunsplit(frags)

if __name__ == "__main__":
    print add_querystring('http://python.org', 'doc', 'urllib')
    print add_querystring('http://python.org?doc=urllib',
                          'page', '2')

E Python 3?

urlparse foi "juntada" com urllib.

Coisas da urllib mudaram de lugar.

Compatível entre 2 e 3

import six

def add_querystring(url, querystring, value):
    frags = list(six.moves.urllib.parse.urlsplit(url))
    query = frags[3]
    query_frags = six.moves.urllib.parse.parse_qsl(query)
    query_frags.append((querystring, value))
    frags[3] = six.moves.urllib.parse.urlencode(query_frags)
    return six.moves.urllib.parse.urlunsplit(frags)

if __name__ == "__main__":
    six.print_(add_querystring('http://python.org', 'doc', 'urllib'))
    six.print_(add_querystring('http://python.org?doc=urllib',
                               'page', '2'))

Perguntas?

E antes que alguém pergunte, é 2 *3, não 2 +3.