Back-End

23 abr, 2012

Dicas, truques e hacks de Python – Parte 1

Publicidade

A versão original enviada pelo autor David Isaacson é em inglês, traduzida pela redação iMasters. A versão em inglês pode ser lida em  http://www.siafoo.net/article/52

?

Quer escrever um código mais curto e limpo? Tem uma situação infeliz em que você precisa pôr o máximo que conseguir dentro de uma expressão? Prefere uma boa e rápida dose de hacks a passar o resto da sua vida lendo os documentos? Você veio ao lugar certo. Começaremos com uns truques rápidos que você já deve ter descoberto se já passou um tempo com o Phyton, mas prometo que há coisas mais aventureiras mais para o final.

Tentei fazer com que todos os trechos do código se executassem sozinhos. Se você quiser, cole-os na sua Python Shell e os teste. Você vai notar muitos exemplos contendo ‘true example’ e ‘false example’, com um comentário. Sinta-se à vontade para trocar o comentário e ver o que acontece.

Você também verá alguns comentários em branco flutuando em volta do código. Seu objetivo é melhorar a legibilidade ao adicionar quebras de linhas ao mesmo tempo em que o intérprete do Phython analisa o código. Isso não seria necessário em um programa ‘real’ (‘não colados’).

Uma rápida distinção entre true vs True neste artigo: quando eu disser que um objeto é ‘true’, quero dizer que o objeto, se convertido a um boolean em uma instrução if ou em qualquer outro lugar, seria convertido a True, e não a False. Isso não significa que o objeto é necessariamente idêntico ou equivalente a True. Da mesma maneira, se eu disser que um objeto é ‘false’, quero dizer que o objeto seria convertido a False, não que ele seja necessariamente idêntico ou equivalente a False.

1 – Truques rápidos

1.1 – Quatro tipos de quotes

Vamos começar com algo rápido que você provavelmente já conhece. Se você está vindo de uma linguagem diferente, provavelmente está acostumado a usar quotes únicos para uma coisa, e quotes duplos para outra. O Phyton te permite usar os dois, apesar de eles não serem intercambiáveis (se você começar com um, você tem que terminar com o mesmo). O Phyton também tem mais dois tipos de quotes. Um quote triplo, ”’, é criado ao digitar três quotes únicos. Um quote duplo-triplo, “””, é criado ao se digitar três quotes duplos. Portanto, você pode ter várias camadas de quoting antes de começar a se preocupar em deixar seus quotes escaparem. Por exemplo, isto é valido no Python:

print """I wish that I'd never heard him say, '''She said, "He said, 'Give me five dollars'"'''"""

1.2 – A verdade de vários objetos

Diferentemente de outras linguagens de programação (cof, cof, Javascript), os Phyton Types são false se estiverem vazios, e true se não estiverem vazios. Isso significa que você não tem que checar, por exemplo, se o comprimento de uma sequência (string), tupla, lista ou dicionário, é 0 ou equivalente a um vazio. É preciso checar apenas a verdade do objeto.

Como você já imaginava, o número zero também é false, enquanto todos os outros números são true.

Por exemplo, as expressões a seguir são equivalentes. Aqui, ‘my_object‘ é um string, mas poderia facilmente ser outro Python type (com as devidas modificações para o teste de igualdade).


my_object = 'Test' # True example
# my_object = '' # False example

if len(my_object) > 0:
print 'my_object is not empty'

if len(my_object): # 0 will evaluate to False
print 'my_object is not empty'

if my_object != '':
print 'my_object is not empty'

if my_object: # an empty string will evaluate to False
print 'my_object is not empty'

Em conclusão, não existe necessidade de checar comprimentos ou equivalências se você só está interessado em saber se o objeto é vazio ou não.

1.3 – Checando se uma string contém uma substring

Aqui vai uma dica rápida que pode ser óbvia, mas precisei de um ano de programação em Phyton para descobri-la.

Você provavelmente sabe que pode testar se uma lista, tupla, ou dicionário contém um item ao testar a expressão ‘item in list‘ ou ‘item not in list‘. Eu nunca imaginei que isso funcionaria para strings também. Eu sempre escrevia o código assim:

string = 'Hi there' # True example
# string = 'Good bye' # False example
if string.find('Hi') != -1:
print 'Success!'

Esse é um código feio. É completamente equivalente a fazer ‘if  substring in  string‘:

string = 'Hi there' # True example
# string = 'Good bye' # False example
if 'Hi' in string:
print 'Success!'

Muito mais limpo e simples. Pode ser óbvio para 99% da população, mas eu gostaria de ter descoberto antes.

1.4 – Imprimindo uma lista de forma bonita

Listas não imprimem bem. É claro que fica óbvio o que é a lista, mas um usuário razoável não quer ver colchetes em volta de tudo. Existe uma solução trivial para isso, usando o método ‘join’ na sequência.

recent_presidents = ['George Bush', 'Bill Clinton', 'George W. Bush']
print 'The three most recent presidents were: %s.' % ', '.join(recent_presidents)
# prints 'The three most recent presidents were: George Bush, Bill Clinton, George W. Bush.

O método ‘join’ transforma a lista em string ao moldar cada item dentro da string, e então os conectando com a string em que o join foi chamado. Inclusive é inteligente não colocar um depois do último elemento.

Uma outra vantagem é que isso é muito rápido, executado em tempo linear. Nunca crie uma string utilizando ‘+’ itens juntos para gerar um for loop: não é somente feio como também é bem mais demorado.

1.5 – Integer vs. Float Division

Por padrão, se você dividir um integer por outro, o resultado será truncado dentro de um integer. Por exemplo, executar 5/2 devolve 2.

Existem duas maneiras de consertar isso. A primeira e mais simples delas é simplesmente transformar um dos integers em um float. Se os valores são estáticos, você pode apenas adicionar um .0 a ele para o transformar em float. 5.0/2 devolve 2.5. Alternativamente, você pode apenas moldar um dos valores: float(5) / 2 devolve 2.5.

A outra maneira vai resultar em um código mais limpo, mas você deve garantir que nenhum dos seus códigos está confiando nessa truncagem. Você pode fazer uma divisão from __future__ import para que o Phyton sempre retorne um float como resultado da divisão. Depois dessa importação, 5/2 vai retornar 2.5. Se você ainda precisar usar a divisão truncada de integer em outro lugar, você então pode usar o the // operator: 5//2 vai sempre devolver 2.

5/2        # Returns 2
5.0/2 # Returns 2.5
float(5)/2 # Returns 2.5
5//2 # Returns 2

from __future__ import division
5/2 # Returns 2.5
5.0/2 # Returns 2.5
float(5)/2 # Returns 2.5
5//2 # Returns 2

Nota

Em algum momento, a divisão de float será a default (padrão). Se você quiser que seu código garantidamente funcione em futuras versões do Python, use o // operator se você quer utilizar a divisão truncada, não importa se você está utilizando a divisão from __future__ import  ou não.

1.6 – Funções lambda

Às vezes, você precisa passar uma função como um argumento, ou você quer fazer uma operação curta – mas complexa – múltiplas vezes. Você pode definir sua função da maneira normal, ou você pode fazer uma função lambda, uma mini-função que devolve o resultado de uma simples expressão. As duas definições são completamente idênticas.

def add(a,b): return a+b

add2 = lambda a,b: a+b

A vantagem da função lambda é que ela própria é uma expressão, e pode ser usada ao lado de outra declaração. Aqui temos um exemplo usando a map function, que chama uma função em cada elemento de uma lista, e devolve uma lista dos resultados. 

squares = map(lambda a: a*a, [1,2,3,4,5])
# squares is now [1,4,9,16,25]

Sem o lambda, você teria que definir a função separadamente. Você apenas salvou uma linha de código e um nome variável (para a função).

Sintaxe: funções lambda

Uma função lambda tem a sintaxe: lambda variable(s) : expression

variable(s)
variável(eis)
Uma lista, variável ou variáveis, separadas por uma vírgula, que uma função pode receber. Você não pode usar palavras-chave, e você não quer que elas estejam em parênteses (um erro que eu cometi por alguns meses e me perguntava por que meus lambdas nunca funcionavam).
Expression
(express
ão)
Uma expressão inline python. O escopo inclui escopos locais e variáveis. Isso é o que a função retorna.

No próximo artigo, falaremos sobre o uso de listas inteligentes, como mapeá-las e filtrá-las e quando devemos usar o generator expressions.