O código deve ser escrito de uma forma que não deixe em desvantagem outras implementações de Python (PyPy, Jython, IronPython, Pyrex, Psyco etc). Por exemplo, não use a implementação eficiente do CPython para concatenação de string "a +=b" ou "a = a + b". Isto corre mais lentamente em Jython. Em partes da biblioteca de performance sensível, ''.join() deve ser usado.
Isto garantirá que a concatenação ocorra em tempo linear entre as diferentes implementações.
Comparações de singletons como None devem ser sempre feitas com 'is' ou 'not', nunca com operadores de igualdade. Além disso, cuidado com "if x" quando você realmente quer dizer "if x is not None" Por exemplo, quando testar se uma variável ou argumento no qual os padrões de None foram definidos para outro valor. O valor pode ter um outro tipo (Como um container), que pode ser falsa em um contexto booleano.
Use exceções baseadas em classes.
Exceções de string em código novo é proibido, porque este recurso da linguagem está sendo removido no Python 2.6.
Módulos ou pacotes devem definir sua própria classe base de exceção para seu domínio específico, que deve ser uma subclasse de Exception. Sempre inclua uma docstring. Por exemplo:
class MessageError(Exception):
"""Base class for errors in the email package."""
Ao levantar uma exceção, use "raise ValueError('message')" no lugar da forma mais antiga "raise ValueError, 'message'".
A forma com parênteses é preferida porque quando os argumentos são longos e incluem a formatação de string, você não precisa usar os caracteres de continuação de linha. A forma antiga será removido no Python 3000.
Mencionar exceções específicas em try: ... except:.
Por exemplo, use:
try:
import platform_specific_module
except ImportError:
platform_specific_module = None
Uma cláusula except: nua pega SystemExit e KeyboardInterrupt Ctrl-C, e pode mascarar outros problemas. Se você quiser pegar todas as exceções que sinalizam erros no programa use "except Exception:".
Uma boa regra é limitar a utilização de cláusulas except nuas para dois casos:
1) Se o manipulador de exceção irá imprimir ou logar o traceback, pelo menos, o usuário estará ciente de que um erro ocorreu.
2) Se o código precisa fazer algum trabalho de limpeza, mas depois deixa a exceção se propagar com "raise". "try: ... finally:"
é a melhor maneira de lidar com este caso. Além disso, para todos os try/excepts limite o try ao mínimo código necessário.
Novamente, isto evitará o mascaramento de erros.
Sim:
try:
value = collection[key]
except KeyError:
return key_not_found(key)
else:
return handle_value(value)
Não:
try:
# Too broad!
return handle_value(collection[key])
except KeyError:
# Will also catch KeyError raised by handle_value()
return key_not_found(key)
Utilize métodos de string ao invés do módulo string.
Os métodos são sempre muito mais rápido e têm a mesma API com strings unicode. Substituir esta regra se a compatibilidade com Python <= 2.0 é necessária.
Use ''.startswith() e ''.endswith() ao invés de slicing para verificar a prefixos ou sufixos. startswith e endswith são mais limpos e menos propensos a erros. Exemplo:
Sim: if foo.startswith ('bar'):
Não: if foo[:3] == 'bar':
A exceção é se o seu código deve trabalhar com Python <= 1.5.2 (mas vamos esperar que não!).
Comparações de tipo de objeto deve sempre usar isinstance() ao invés de comparação direta de tipos.
Sim: if isinstance(obj, int):
Não: if type(obj) is type(1):
Ao verificar se um objeto é uma string, tenha em mente que também poderia ser uma string unicode! Em Python 2.3, str e unicode têm uma classe base basestring, de modo que você pode fazer:
if isinstance(obj, basestring):
Em Python 2.2, o módulo de tipos tem o tipo StringTypes definido para esse efeito, por exemplo:
from types import StringTypes
if isinstance(obj, StringTypes):
Em Python 2.0 e 2.1, você deve fazer:
from types import StringType, UnicodeType
if isinstance(obj, StringType) or \
isinstance(obj, UnicodeType):
Para as sequências (strings, listas, tuplas), use o fato de que sequencias vazias são falsas.
Sim: if seq:
Não: if len(seq):
Não escrever literais string que dependem de espaços em branco no final. A quantidade desses espaços é visualmente indistinguível e alguns editores (ou, mais recentemente reindent.py), vai cortá-las.
Não compare valores booleanos usando ==:
Sim: if greeting:
Não: if greeting == True:
Pior: if greeting is True: