Curso
PEP-8, ou Python Enhancement Proposal, apresenta pontos essenciais para deixar seu código mais organizado e legível. Como diz o criador do Python, Guido Van Rossum:
O código é lido com muito mais frequência do que é escrito.
Neste post, você vai começar a explorar a PEP-8 com exemplos de código! Vamos abordar:
- Primeiro, uma introdução ao que é a PEP-8 e por que você precisa dela;
- Depois, vamos falar de indentação, um tema quente entre programadores. Usar tabs ou espaços? Você vai descobrir a resposta nesta seção;
- Talvez você não espere, mas há diretrizes para o comprimento máximo das linhas;
- Também existe uma forma proposta de lidar com linhas em branco;
- Em seguida, espaços em expressões e instruções: algo que você pode dominar facilmente, mesmo como iniciante;
- O que é codificação (encoding) e por que você precisa disso em Python? Qual é o encoding padrão no Python 3? A seção sobre codificação do arquivo-fonte explica tudo isso.
- Você provavelmente faz imports com frequência ao programar. Esta seção cobre a ordem dos imports, imports absolutos e relativos, wildcard imports, etc.;
- Documentação é essencial para acompanhar todos os aspectos de uma aplicação e elevar a qualidade do produto final. Comentários são fundamentais aqui!
- Você conhece os dunder names em nível de módulo? Eles são particularmente úteis em docstrings!
- Por fim, você também vai ver convenções de nomenclatura: como criar nomes de funções, quais estilos usar e muito mais;
- Seu código está em conformidade com a PEP-8? Essa é uma pergunta que você deveria se fazer. Por isso, a última seção traz ferramentas para checar se seu código segue as diretrizes apresentadas aqui e várias outras que não couberam neste post!
uma introdução à PEP-8
Python se consolidou como uma das linguagens preferidas por muita gente. É relativamente fácil de aprender, é multiparadigma, tem muitos módulos open source que ampliam sua utilidade e é uma ferramenta queridinha nas comunidades de ciência de dados e desenvolvimento web.
Mas você só aproveita todo esse potencial quando sabe expressar melhor suas ideias com código. Python foi criado com alguns princípios em mente — dá para vê-los quando você digita import this.
import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
Esses são os 20 princípios do Python, conhecidos como o Zen of Python. Repare no "Readability counts" — legibilidade conta —, que deve ser sua principal preocupação ao escrever código: outras pessoas desenvolvedoras ou cientistas de dados precisam entender e conseguir contribuir para que o código resolva o problema.
As seções a seguir mostram como chegar lá!
indentação
Programando em Python, você vai usar indentação o tempo todo. Mas cuidado: erros aqui viram erros de sintaxe. A recomendação é usar quatro espaços por nível de indentação. Por exemplo, esta instrução usa quatro espaços:
if True:
print("If works")
Este for com print também está indentado com quatro espaços:
for element in range(0, 5):
print(element)
Ao escrever expressões longas, é melhor alinhar verticalmente os elementos. Assim, você cria um "hanging indent".
Veja alguns exemplos de hanging indent em expressões maiores, com variações de uso:
-
value = square_of_numbers(num1, num2, num3, num4) -
def square_of_number( num1, num2, num3, num4): return num1**2, num2**2, num3**2, num4**2 -
value = square_of_numbers( num1, num2, num3, num4) -
list_of_people = [ "Rama", "John", "Shiva" ] -
dict_of_people_ages = { "ram": 25, "john": 29, "shiva": 26 }
Todo mundo que programa em Python (ou outra linguagem) se pergunta em algum momento: usar tabs ou espaços para indentar? A diferença entre tabs e espaços é um debate antigo na comunidade. Confira, por exemplo, este artigo do Stack Overflow.
No geral, espaços são preferidos. Mas, se você encontrar um script Python que já usa tabs, siga com tabs para manter a consistência. Caso contrário, troque a indentação de todas as expressões para espaços.
Observação: o Python 3 não permite misturar tabs e espaços. Escolha um e siga com ele!
comprimento máximo da linha
É uma boa prática manter suas linhas de código com até 79 caracteres.
Seguir esse limite traz várias vantagens, como:
- Abrir arquivos lado a lado para comparar fica viável;
- Você vê a expressão inteira sem rolar horizontalmente, o que melhora a leitura e o entendimento.
Comentários devem ter até 72 caracteres por linha. Mais adiante você verá convenções comuns para comentários!
No fim, em times pequenos, vocês podem ajustar as convenções conforme o estilo do time, e às vezes é aceitável fugir desse limite. Porém, em projetos open source, você provavelmente vai querer (e/ou precisar) seguir a regra de comprimento máximo definida pela PEP-8.
Ao usar o operador +, prefira quebrar a linha de forma apropriada para facilitar a leitura:
| Use... | Evite... |
|---|---|
|
|
|
Como alternativa, você também pode escrever:
total = A
+ B
+ C
Em resumo, você pode quebrar a linha antes ou depois de um operador binário, desde que seja consistente. Se estiver escrevendo código novo, tente seguir a última opção apresentada, quebrando a linha antes do operador.
linhas em branco
Em scripts Python, funções e classes de nível superior são separadas por duas linhas em branco. Definições de métodos dentro de classes devem ser separadas por uma linha em branco. Veja o exemplo:
import unittest
class SwapTestSuite(unittest.TestCase):
"""
Swap Operation Test Case
"""
def setUp(self):
self.a = 1
self.b = 2
def test_swap_operations(self):
instance = Swap(self.a,self.b)
value1, value2 =instance.get_swap_values()
self.assertEqual(self.a, value2)
self.assertEqual(self.b, value1)
class OddOrEvenTestSuite(unittest.TestCase):
"""
This is the Odd or Even Test case Suite
"""
def setUp(self):
self.value1 = 1
self.value2 = 2
def test_odd_even_operations(self):
instance1 = OddOrEven(self.value1)
instance2 = OddOrEven(self.value2)
message1 = instance1.get_odd_or_even()
message2 = instance2.get_odd_or_even()
self.assertEqual(message1, 'Odd')
self.assertEqual(message2, 'Even')
As classes SwapTestSuite e OddOrEvenTestSuite estão separadas por duas linhas em branco, enquanto métodos como .setUp() e .test_swap_operations() têm apenas uma linha em branco entre si. O código executa sem gerar saída, pois falta o trecho para rodar os testes (o objetivo é apenas mostrar boas práticas).
espaços em expressões e instruções
Evite espaços desnecessários como nos exemplos abaixo:
| Use... | Evite... |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ou
ou
|
|
|
|
|
|
|
Estes exemplos foram retirados da PEP-8.
codificação do arquivo-fonte
Um computador não armazena "letras", "números", "imagens" ou qualquer outra coisa; Ele só armazena e trabalha com bits, que têm valores binários: sim ou não, verdadeiro ou falso, 1 ou 0 etc. Como você sabe, computadores funcionam com eletricidade; Isso significa que um bit "real" é a presença ou ausência de um pulso elétrico. Costumamos representar essa presença (ou ausência) com 1 e 0.
Para usar bits para representar qualquer coisa além de bits, você precisa de um conjunto de regras. É preciso converter uma sequência de bits em letras, números e imagens usando um esquema de codificação (encoding). Exemplos: ASCII, UTF-8 etc.
- ASCII (American Standard Code for Information Interchange) é o formato mais comum para arquivos de texto em computadores e na Internet. Nesse tipo de arquivo, cada caractere alfabético, numérico ou especial é representado por um número binário de 7 bits (uma sequência de sete 0s ou 1s).
- Unicode (Unicode Worldwide Character Standard) é um sistema para "a troca, processamento e exibição dos textos escritos das diversas línguas do mundo moderno". Em resumo, o Unicode foi projetado para acomodar todos os sistemas de escrita conhecidos. Atualmente, o Unicode usa três codificações: UTF-8, UTF-16 e UTF-32.
- UTF-16 é uma codificação de comprimento variável: pontos de código são representados por uma ou duas unidades de 16 bits.
- UTF-8 é outra codificação Unicode de comprimento variável, usando de um a quatro bytes de 8 bits.
- UTF-32 é uma codificação de comprimento fixo, que usa exatamente 32 bits por ponto de código.
Dica: se quiser saber mais sobre encoding, confira este post.
Agora, por que isso é importante?
Strings estão entre os tipos de dados mais usados em Python. E vai chegar a hora em que você vai trabalhar com strings que contêm caracteres fora do conjunto ASCII padrão. Afinal, pode ser necessário lidar com textos com acentos, como á, ž, ç etc.
No Python 3, UTF-8 é o encoding padrão do arquivo-fonte. Já no Python 2, o padrão era ASCII.
Mas e se você tiver uma string com um caractere não ASCII, como "Flügel"?
Ao referenciar a string no Python 2, você verá algo assim:
>>> s
'Fl\xfcgel'
Não é bem a sua string! E se você imprimir?
>>> print(s)
Flügel
Ao imprimir, você vê o valor atribuído à variável. O caractere não ASCII ÃŒ foi codificado. Por isso você obteve \xfc ao referenciar a string. Para lidar com isso, use os métodos .encode() e .decode(): o primeiro retorna uma versão 8-bit da string Unicode, no encoding solicitado; o segundo interpreta a string usando o encoding informado.
imports
Importar bibliotecas e/ou módulos é algo que você fará com frequência ao usar Python para data science. Como você já deve saber, é recomendado fazer os imports no início do script.
Observação: se fizer muitos imports, declare cada um em uma linha.
Veja a tabela a seguir para entender melhor:
| Use... | Evite... |
|---|---|
|
ou
|
|
Além disso, existe uma ordem recomendada para importar bibliotecas. Em geral, siga:
- Imports da biblioteca padrão.
- Imports de terceiros relacionados.
- Imports específicos da aplicação/biblioteca local.
imports absolutos e relativos
É importante conhecer a diferença entre imports absolutos e relativos. Em geral, imports absolutos são preferíveis em Python, pois aumentam a legibilidade. Porém, conforme a aplicação cresce, imports relativos também podem ser úteis. Imports relativos implícitos não devem ser usados e foram removidos no Python 3.
Mas o que são eles?
-
Um import absoluto usa o caminho completo da função ou classe, separado por
.. Por exemplo,import sklearn.linear_model.LogisticRegression -
Um import relativo é relativo à posição atual do seu arquivo Python. Esse tipo de import ajuda a manter projetos grandes mais legíveis. Suponha a estrutura a seguir:
. ├── __init__.py ├── __init__.pyc ├── __pycache__ │ ├── __init__.cpython-35.pyc │ ├── bubble_sort.cpython-35.pyc │ ├── selection_sort.cpython-35.pyc ├── bubble_sort.py ├── heap_sort.py ├── insertion_sort.py ├── insertion_sort.pyc ├── merge_sort.py ├── merge_sort.pyc ├── quick_sort.py ├── radix_sort.py ├── selection_sort.py ├── selection_sort.pyc ├── shell_sort.py ├── tests │ ├── test1.py
Você poderia usar um import relativo para trazer o algoritmo BubbleSort, definido em bubble_sort.py, para test1 assim:
from ..bubble_sort import BubbleSort
Para saber mais sobre imports absolutos e relativos, veja a PEP 328.
wildcard imports
Evite wildcard imports, pois prejudicam a legibilidade: você perde visibilidade sobre quais classes, métodos ou variáveis estão sendo usadas do módulo. Por exemplo:
from scikit import *
comentários
Comentários funcionam como documentação in-line em Python. Eles ajudam a entender o código. Existem várias ferramentas para gerar documentação (comentários e docstrings) para seus módulos. Comentários devem ser descritivos para que qualquer pessoa lendo o código entenda o que ele faz e como se integra com outras partes.
Comentários começam com o símbolo #. Tudo que vem depois não é executado pelo interpretador. Por exemplo, o trecho a seguir retorna apenas "This is a Python comment".
# This is a Python single line comment
print("This is a Python comment")
Lembrete: como visto antes, comentários devem ter até 72 caracteres por linha!
Existem três tipos de comentários:
- Use comentários em bloco para explicar trechos mais complexos ou pouco familiares. Normalmente são mais longos e se aplicam ao código que vem na sequência. Eles são indentados no mesmo nível do código e cada linha começa com
#e um espaço. Se precisar de mais de um parágrafo, separe-os com uma linha contendo apenas#.
Veja o trecho a seguir, retirado da biblioteca scikit-learn, para entender como ficam:
if Gram is None or Gram is False:
Gram = None
if copy_X:
# force copy. setting the array to be fortran-ordered
# speeds up the calculation of the (partial) Gram matrix
# and allows to easily swap columns
X = X.copy('F')
- Use comentários in-line com moderação, embora sejam úteis para explicar partes específicas do código. Eles também ajudam você a lembrar o que uma linha faz ou apoiar quem está colaborando com seu código. Ficam na mesma linha da instrução, após o código, começando com
#e um espaço.
Exemplo:
counter = 0 # initialize the counter
- Docstrings são escritas no início de módulos, arquivos, classes e métodos públicos. Começam com
"""e terminam com""":
"""
This module is intended to provide functions for scientific computing
"""
dunder names em nível de módulo
Agora que você já viu o que são docstrings, vale conhecer também os dunders em nível de módulo, ou nomes com dois underscores no início e no fim. Eles são especiais em Python e evitam conflitos com nomes definidos pelo usuário. Para saber mais, veja este artigo.
Dunders de módulo como (__all__, __author__, __version__) devem ficar após a docstring principal do módulo e antes de quaisquer instruções import. Os imports from __future__ devem vir antes de qualquer outro código, exceto docstrings:
"""
Algos module consists of all the basic algorithms and their implementation
"""
from __future__ import print
__all__ = ['searching', 'sorting']
__version__ = '0.0.1'
__author__ = 'Chitrank Dixit'
import os
import sys
Dica: confira as convenções para escrever docstrings.
convenções de nomenclatura
Programando em Python, você certamente vai adotar convenções de nomenclatura — um conjunto de regras para escolher as sequências de caracteres usadas como identificadores de variáveis, tipos, funções e outras entidades no código e na documentação.
Se você não tem clareza sobre os estilos existentes, considere estes:
bou uma única letra minúscula;Bou uma única letra maiúscula;lowercaseUPPERCASElower_case_with_underscoresUPPER_CASE_WITH_UNDERSCORESCapitalizedWords, também conhecido comoCapWords,CamelCaseouStudlyCaps.mixedCaseCapitalized_Words_With_Underscores_single_leading_underscore: indicador fraco de "uso interno". Por exemplo,from M import *não importa objetos cujo nome começa com underscore.single_trailing_underscore_: usado por convenção para evitar conflito com palavras-chave do Python, por exemplo,Tkinter.Toplevel(master, class_='ClassName')__double_leading_underscore: ao nomear um atributo de classe, aciona name mangling (dentro da classeFooBar,__boovira_FooBar__boo).__double_leading_and_trailing_underscore__: objetos ou atributos "mágicos" que vivem em namespaces controlados pelo usuário. Ex.:__init__,__import__,__file__. Não invente esses nomes; use apenas os documentados.
guias gerais de nomes
A tabela a seguir mostra diretrizes gerais para nomear identificadores:
| Identificador | Convenção |
|---|---|
| Módulo | lowercase |
| Classe | CapWords |
| Funções | lowercase |
| Métodos | lowercase |
| Variáveis de tipo | CapWords |
| Constantes | UPPERCASE |
| Pacote | lowercase |
- Não use 'l', 'O' ou 'I' como nomes de variável únicos: em algumas fontes, eles se parecem com zero (
0) e (1). - Em geral, prefira nomes curtos quando possível. Em alguns casos, use underscores para melhorar a legibilidade.
Para ver exceções às diretrizes gerais, consulte este artigo.
seu código está em conformidade com a PEP-8?
Depois de conhecer a PEP-8, você deve estar se perguntando como verificar se seu código realmente segue essas diretrizes (e várias outras que não cobrimos aqui!).
Além de estudar a PEP-8 por conta própria, vale muito experimentar o módulo pep8, o pacote coala e outras alternativas descritas a seguir!
pacote Python pep8
O pacote pep8 verifica incompatibilidades com a PEP-8 no seu código Python e sugere mudanças para adequação. Você pode instalar o módulo com pip executando:
pip install pep8
Para demonstrar o pep8, crie um arquivo example.py com o seguinte código:
def my_function(a, b):
print("The sum of a and b is: ", a + b)
a = 1
b = 2
my_function(a,b)
Salve o arquivo e rode o comando pep8 no terminal assim:
pep8 example.py
Você verá as incompatibilidades detectadas, algo como:
example.py:1:1: E302 expected 2 blank lines, found 0
example.py:3:5: E225 missing whitespace around operator
example.py:5:5: E225 missing whitespace around operator
A primeira linha indica que deveriam existir duas linhas em branco antes da definição de função na linha 1. As duas seguintes indicam que faltam espaços ao redor do operador de adição no print e nas atribuições.
Para corrigir, altere o código para:
def my_function(a, b):
print("The sum of a and b is:", a + b)
a = 1
b = 2
my_function(a, b)
Agora, ao rodar pep8 example.py novamente, não deverá haver saída — sinal de que o código está conforme a PEP-8.
Você também pode ver o trecho do código com o erro usando --show-source:
$ pep8 --show-source --show-pep8 testsuite/E40.py
testsuite/E40.py:2:10: E401 multiple imports on one line
import os, sys
^
Imports should usually be on separate lines.
Okay: import os\nimport sys
E401: import sys, os
Ou exibir estatísticas de frequência de cada erro com --statistics:
$ pep8 --statistics -qq Python-2.5/Lib
232 E201 whitespace after '['
599 E202 whitespace before ')'
631 E203 whitespace before ','
842 E211 whitespace before '('
2531 E221 multiple spaces before operator
4473 E301 expected 1 blank line, found 0
4006 E302 expected 2 blank lines, found 1
165 E303 too many blank lines (4)
325 E401 multiple imports on one line
3615 E501 line too long (82 characters)
612 W601 .has_key() is deprecated, use 'in'
1188 W602 deprecated form of raising exception
Dica: experimente também módulos como flake8, autopep8 ou pylint!
analisando seu código com coala
O coala oferece lint e correções para várias linguagens, mas aqui o foco é Python. Instale o coala com pip:
$ pip3 install coala-bears
No comando acima, repare que instalamos coala-bears: os bears são plugins que estendem as capacidades do coala e variam por linguagem. Neste caso, use o pep8bear, que encontra e corrige incompatibilidades com a PEP-8. Vale muito para checar seu código Python.
$ coala -S python.bears=PEP8Bear python.files=\*\*/\*.py \
python.default_actions=PEP8Bear:ApplyPatchAction --save
# other output ...
Executing section python...
[INFO][11:03:37] Applied 'ApplyPatchAction' for 'PEP8Bear'.
[INFO][11:03:37] Applied 'ApplyPatchAction' for 'PEP8Bear'.
pep8online: verifique seu código Python online
Além do módulo pep8 e do pacote coala, você também pode checar se seu código está conforme a PEP-8 acessando o pep8online. O site tem um editor online: cole seu código, clique em "Check code" e pronto! Você recebe um feedback do que melhorar. Prático e rápido!
conclusão
Ao usar Python, às vezes a pressa por lançar funcionalidades faz a gente relaxar com a qualidade do código. No entanto, as práticas deste tutorial — e muitas outras que não couberam aqui — deveriam fazer parte do seu ciclo de desenvolvimento, testes e deploy. Isso ajuda todo mundo no projeto a entender o que está acontecendo e, na maioria das vezes, permite modificar o código sem mergulhar fundo no debugger. Em projetos open source, quem contribui agradece: seguir a PEP-8 facilita a vida e melhora a compreensão do código, já que é o padrão mais difundido entre desenvolvedores Python.
Agora que você passou por este guia, vale muito a pena ler a PEP-8 original! Tem muito mais para descobrir.
Tem mais dicas para seguir a PEP-8 ou acha que ficou faltando algo importante? Fala com a gente no @DataCamp.

