Python para oceanógrafos/Primeiros passos

Bibliotecas

editar

Este guia é baseado em Python versão 2.7 e utiliza bibliotecas promovidas pela NumPy Foundation for Open Code for Usable Science (NumFOCUS)[1]. A NumFOCUS tem por missão patrocinar o desenvolvimento de linguagens the alto nível para ciência; promover estudos com orientação a matrizes e abordagens computacionais de altas ordens e ciência computacional aplicada; promover o uso de código aberto e incentivar a pesquisa reprodutível. Dentre os seus principais projetos, destacam-se

  • NumPy. Pacote fundamental para computação científica com Python. Numpy adiciona uma ferramenta rápida e sofisticada para manipulação de matrizes à linguagem Python. Ela é requisito para as duas bibliotecas citadas acima e é instalada automaticamenteo ao instalar-se qualquer uma delas.
  • SciPy. Ferramentas científicas para Python (Scientific tools for Python) é uma biblioteca que possui manipulação de matrizes n-dimensionais rápida e conveniente. Ela fornece uma série de rotinas numéricas amigáveis para integração, otimização numérica e análise estatística avançada.
  • matplotlib. Biblioteca para criação de gráficos e figuras de alta qualidade em uma variedade de formatos. Também possui ferramentas para a criação de mapas através do complemento “basemap”.
  • pandas. Biblioteca para estrutura de dados e ferramentes de análise de dados. É de uso fácil e de alta performance.
  • scikits-learn. Módulo destinado a resolver problemas de aprendizagem de máquina (machine learning) de forma acessível.
  • scikits-image. Coleção voluntária de algoritmos de alta qualidade e revisada por pares para processamento de imagens.

Para aplicações oceanográficas, também existem as seguintes bibliotecas que extendem as funcionalidades:

  • seawater. O pacote fornece funções básicas para determinar propriedades físicas da água do mar como densidade, calor armazenado, etc.
  • PyDAP Biblioteca que implanta o protocolo de acesso a dados DAP, também conhecido por DODS ou OPeNDAP.

Algumas operações

editar

Funções lambda

editar
 lon180 = lambda x: x + (x <= -180) * 360 - (x > 180) * 360

Estatísticas simples

editar
  • Média
  • Desvio padrão
  • Mínimo
  • Máximo
  • Mediana

Primeiro gráfico

editar
 # -*- coding: iso-8859-1 -*-
 import pylab
 
 v0 = -10. # Velocidade inicial (m/s)
 a = 2.5   # Aceleracao (m**2/s)
 
 t = pylab.arange(0., 10.1, 0.1)
 v = v0 + v0 * t + 0.5 * a * t ** 2
 
 pylab.plot(t, v)
 pylab.title(u'Movimento uniformimente variavel')
 pylab.xlabel('Tempo (s)')
 pylab.ylabel('Velocidade (m/s)')
 pylab.show()

Guia de estilo

editar

Um aspecto importante na hora de se escrever código em qualquer linguagem é a legibilidade, principalmente levando-se em conta que código é lido com maior frequência que escrito. Por isso Guido van Rossum e Barry Warsaw sugerem um guia estilo para a formatação de código na linguagem Python. A íntegra em inglês deste guia pode ser consultada no atalho ao lado Guia de estilo para código Python. Ele foi elaborado para garantir consistência no código escrito. Atenção na formatação do código e na sua documentação é importante para consultas futuras, principalmente para justificar determinadas soluções adotadas quando não podemos contar com nossa memória. Um resumo do guia de estilo citado é apresentado a seguir.

Leiaute

editar

Identação

editar

Cada nível de identação deve ser composto por quatro (4) espaços. O uso de tabulações não é recomendado e não se deve misturar tabulações com espaços. Os principais editores disponíveis possuem recursos para a utilização de espaços ao invés da tabulação.

Extensão das linhas

editar

As linhas de código não devem possuir mais de 79 caracteres. Muitos dispositivos de exibição são limitados a 80 caracteres cuja quebra de texto pode distorcer a estrutura visual do código, dificultando a sua compreensão. Para blocos de texto longos (documentação ou comentários), recomenda-se o limite de 72 caracteres por linha. Seguindo estas recomendações pode-se, em dispositivos de maior resolução, utilizar múltiplas janelas de código lado a lado para consulta simultânea.

Continuação de linha implícita do Python pode ser feita entre parênteses (( )), colchetes ([ ]) ou chaves ({ }). Linhas compridas podem ser divididas envolvendo-se expressões entre parênteses, mantendo a identação apropriada. A região preferida para quebra de operadores binários é após o operador ao invés de antes dele. O código a seguir ilustra um exemplo de quebra de linhas.

# -*- coding: iso-8859-1 -*-
class Rectangle(Blob):
    def __init__(self, width, height,
                 color='black', emphasis=None, highlight=0):
        if (width == 0 and height == 0 and
            color == 'red' and emphasis == 'strong' or
            highlight > 100):
            raise ValueError("sorry, you lose")
        if width == 0 and height == 0 and (color == 'red' or
                                           emphasis is None):
            raise ValueError("I don't think so -- values are %s, %s" %
                             (width, height))
        Blob.__init__(self, width, height,
                      color, emphasis, highlight)

Linhas em branco

editar

Separe as definições de funções e de classes de nível superior com duas linhas em branco. Definições de métodos dentro de uma classe são separadas por uma única linha. Linhas em branco extras podem ser utilizadas moderadamente para separar grupos de funções relacionadas. Nas funções utilize linhas em branco para indicar seções lógicas.

Codificação de caracteres

editar

Todo o código Python deve utilizar a codificação de caracteres ASCII ou Latin-1 (ISO-8859-1). Para Python 3.0 ou superior a codificação preferida é UTF-8.

Importações

editar

Comandos de importação devem estar em linhas separadas, como por exemplo em

 import os
 import sys
 import numpy
 

Deve-se evitar

  import os, sys, pylab
 

No entanto, para a importação de funções de uma mesma biblioteca pode-se utilizar

from numpy import array, cos, pi
 

As importações devem ser listadas no topo do arquivo, logo abaixo da documentação e dos comentários do módulo. Elas devem ser agrupadas seguindo a seguinte ordem:

  1. Módulos da biblioteca padrão;
  2. Módulos de terceiros relacionados;
  3. Módulos locais e/ou específicos para a aplicação.

Deve-se separar grupos de importação por uma linha em branco. Qualquer especificação __all__ deve ser feita após as importações.

Espaços em branco

editar

Em expressões ou declarações, evite espaços em branco estranhos nas seguintes situações:

  • Imediatamente dentro de parênteses, colchetes ou chaves;
fruta(maca[1], {pera: 2})
 
fruta( maca[ 1 ], { pera: 2 } )
 
  • Imediatamente antes de uma vírgula, ponto-e-vírgula e dois-pontos;
if x == 4: print x, y; x, y = y, x
 
if x == 4 : print x , y ; x , y = y , x
 
  • Imediatamente antes de parênteses que inicia a lista de argumentos de uma chamada de função;
fruta(1)
 
fruta (1)
 
  • Imediatamente antes de parênteses de abertura que inicia uma indexação ou corte;
dict['chave'] = list[indice]
 
dict ['chave'] = list [indice]
 
  • Mais de um espaço ao redor de um operador de atribuição para alinhamento.
x = 1
y = 2
var_longa = 3
 
x         = 1
y         = 2
var_longa = 3
 

Outras recomendações:

  • Sempre cerque os seguintes operadores binários com um espaço simples de cada lado: atribuição =, atribuição de incremento +=, -=, ...), comparações (==, <, >, !=, <>, <=, >=, in, not in, is, is not), booleanos (and, or, not);
  • Utilize espaços ao redor de operadores aritméticos;
i = i + 1
enviado += 1
x = x * 2 - 1
hipot2 = x * x + y * y
c = (a + b) * (a - b)
 
i=i+1
enviado +=1
x = x*2 - 1
hipot2 = x*x + y*y
c = (a+b) * (a-b)
 
  • Não utilize espaços ao redor do sinal de = quando indicar um argumento de palavra-chave ou um valor de parâmetro padrão;
def complexo(real, imag=0.0):
    return magico(r=real, i=imag)
 
def complexo(real, imag = 0.0):
    return magico(r = real, i = imag)
 
  • O uso de instruções compostas~(múltiplas instruções na mesma linha) não é recomendado;
if oque == 'blah':
    fazer_blah()
fazer_um()
fazer_dois()
fazer_tres()
 
if oque == 'blah': fazer_blah()
    fazer_um(); fazer_dois(); fazer_tres()
 

Comentários

editar

Comentários são utilizados para inserir anotações no módulo que sejam legíveis a qualquer programador. Eles são incluídos para facilitar a compreensão do código. Um bom comentário não pode contradizer o código escrito. Tenha cuidado em manter os comentários atualizados quando houver mudança no código. Eles devem ser sentenças completas respeitando as normas gramaticais e terminando com um ponto final. Para código de uso pessoal ou restrito, os comentários podem ser em qualquer idioma. Para códigos mais abrangentes, recomenda-se redigir os comentários em inglês.

Em bloco. Comentários em bloco geralmente aplicam-se a todo ou parte do código que se segue. Eles devem ser identados no mesmo nível deste código. Cada linha de um comentário em bloco inicia com um caractere # e um espaço simples. Parágrafos dentro do bloco são separados por uma linha contendo apenas um # devidamente identado.

Em linha. Utilize comentários em linha com moderação. Este comentário deve estar na mesma linha da declaração, separado de ao menos dois espaços. Ele inicia com um caractere \lstinline{#} e um espaço simples. Comentários em linha podem ser desnecessários e até distrair quando afirmam o óbvio. Veja os exemplos abaixo:

x = x + 1     # Compensa borda
 
x = x + 1     # Incrementa x
 

Documentação

editar

Escreva a documentação (docstrings) para todos os módulos, funções, classes e métodos públicos. Ele é a sequência literal que segue a declaração de um módulo, função, classe ou método. Esta sequência torna-se o atributo especial __doc__ deste objeto. Documentação não é necessária para métodos não-públicos, entretanto deve haver uma descrição sobre a funcionalidade do método. A sequência deve estar entre """(...)""" como ilustrado a seguir:

def complexo(real=0.0, imag=0.0):
    """Forma um numero complexo.
    
    Argumentos:
        real -- a parte real (padrao 0.0)
        imag -- a parte imaginaria (padrao 0.0)
    
    """
    ...

Note que o trio de aspas """ que fecha a documentação está em uma linha por sí só e é preferencialmente precedida por uma linha em branco. Para o caso de texto descritivo de uma linha apenas, as aspas de fechamento podem estar na mesma linha.

Versões

editar

Manter registro e controle de revisões e versões é importante para certificar-se de que se está trabalhando com a versão mais atualizada. As seguintes linhas devem ser incluidas após a sequência de documentação do módulo e antes de qualquer outro código, separado por uma linha em branco acima e abaixo. Além de manter o controle de versões de cada módulo, sistemas de controle de revisão como Subversion, Github ou CVS podem propagar atualizações automaticamente.

__version__ = "$Revision: 1234 $"
# $Source$

Convenções de nomenclatura

editar

Há diversos estilos de nomenclatura e é importante ser capaz de reconhecer cada um deles, independentemente de seu uso. Distingue-se comumente os seguintes estilos:

  • b -- letra minúscula simples;
  • B -- letra maiúscula simples;
  • minúsculas;
  • minúsculas_com_traço_baixo;
  • MAIÚSCULAS;
  • MAIÚSCULAS_COM_TRAÇO_BAIXO;
  • IniciaisMaiúsculas ou CamelCase. Note que, neste caso, as abreviações devem ser utilizadas na forma maúscula (ex.: HTTPServerError);
  • caixaMista;
  • Palavras_Capitalizadas_Com_Traço_Baixo.

As seguintes formas especias que utilizam o traço baixo como prefixo ou sufixo também são reconhecidas:

  • _traço_baixo_inicial — indicador de uso interno. Por exemplo, from M import * não importa os objetos cujo nome inicia com um traço baixo;
  • traço_baixo_final_ — utilizado por convenção para evitar conflitos com palavras-chave do Python~(ex.: Tkinter.Toplevel(master,class_='ClassName');
  • __traço_baixo_inicial_duplo — ao nomear um atributo de classe, invoca a deformação de seu nome;
  • __traço_baixo_inicial_e_final_duplos__ — objetos `mágicos' que existem em espaços de nome controlados pelo usuário (ex.: __init__, __import__ ou __file__). Nunca invente estes nomes, utilize apenas como documentado.


Exercícios

editar

Exercício 1. Descreva um algoritmo para (...)

Referências