quinta-feira, fevereiro 22, 2007

Caminho do import

Quando importamos um módulo, como o interpretador Python sabe onde ele está?
Na verdade existe uma lista de locais de onde esses modulos são importados.Para vê-la, basta digitar da linha de comando:

>>> from sys import path
>>> path
['', '/usr/lib/python24.zip', '/usr/lib/python2.4', '/usr/lib/python2.4/plat-linux2', '/usr/lib/python2.4/lib-tk', '/usr/lib/python2.4/lib-dynload', '/usr/local/lib/python2.4/site-packages', '/usr/lib/python2.4/site-packages', '/usr/lib/python2.4/site-packages/HTMLgen', '/usr/lib/python2.4/site-packages/Numeric', '/usr/lib/python2.4/site-packages/PIL', '/usr/lib/python2.4/site-packages/cairo', '/usr/lib/python2.4/site-packages/gst-0.10', '/usr/lib/python2.4/site-packages/gtk-2.0', '/usr/lib/site-python']

E para adicionar um caminho, basta utliziar o método 'append' de lista. Assim podemos adicionar um local para o interpretador buscar os módulos que nós vizemos.

quarta-feira, fevereiro 21, 2007

from 'modulo' import *

Para importar um modulo em Python, basta fazer:

import 'modulo'

isso não e nenhum misterio. Do mesmo jeito que para importar apenas um método ou uma função de um módulo é bem simples:

from 'modulo' import 'algo'

Mas você já deve ter visto o from 'modulo' import *.
Isso importa todu que tem no módulo. Mas ai você se pergunta: e por que não usar somente o import 'modulo' ?
Quando usamos somente o import, todas as funções e atributos desse módulo importado não pertencem ao namespace do nosso modulo, ou seja, caso importamos o módulo 'teste', por exemplo, caso queira me referir a uma função de 'teste' eu terei que fazer:

teste.nome_da_função

já se eu usar o from teste import *, todas as funções e métodos do modulo 'teste' importado serão variaveis locais do meu modulo. E não será mais preciso usar a sintaxe acima.

Um pouco mais de namespaces aqui.

Namespaces, locals() e globals()

Quando nós criamos uma variável, onde ela fica guardada exatamente? Isso vai depender de onde ela foi criada. Caso tenha sido dentro de uma função, ela só existirá para aquela função, será uma variável local, pertencendo a um "namespace" local, e quando essa função não for mais usada, a variavel desaparecerá.

Namespaces são onde ficam registradas as variáveis, e funcionam como um dicionário, onde as chaves são os nomes das variáveis, e os valores são os valores dessas variáveis. Existem três tipos de namespaces:

- Namespace local: como citado acima, se refere a uma função ou método de classe. As variáveis desse namespace só poderão ser acessadas de sua função ou método de classse onde ela pertence.

- Namespace global: é onde ficam todas as variáveis, funções, classes, módulos importados, do módulo corrente. Normalmente esse namespace dura até o fim do programa.

- Namespace embutido: esse é acessível de qualquer módulo, e contém funções e excessões embutidas. Ele é criado quando o interpretador python é aberto, e dura até ele ser fechado. As variaveis desse namespace ficam em um módulo, chamado __builtin__.

Quando, no meio do código, existe uma chamada a uma variável, o interpretador python segue uma sequencia de busca pra achar o valor dessa variável. Primeiro ele procura no namespace local, não achando, procura no namespace global, em seguida no namespace embutido. Caso exista uma função aninhada ou lambda dentro de outra, procura-se primeiro no namespace dessa função, depois no da função ascendente e so depois no global e embutido.

Outra definição interessante é a de escopo. Escopo é uma região textual de um programa em Python, onde um namespace é diretamente acessível. O escopo local de uma função é a região de codigo dela, onde podemos chamar suas variáveis diretamente.

Python tem duas funções muito interessantes, com elas podemos acessar os namespaces em tempo de execução, são elas locals() e globals().

A função locals() retorna um dicionário, onde as chaves são os nomes das variáveis locais, e os valores são os valores dessas varáveis. Vamos ver um exemplo:

def f(n):
....mult = n * 2
....print locals()

Obeserve a função acima f(n), 'n' é o argumento da função, argumentos também pertencem ao namespace local, e dentro da função criamos a variável 'mult'. Agora vamos chamar a função atribuindo um valor para 'n':

>>> f(4)
{'mult': 8, 'n': 4}

Obeserve que locals() retornou o dicionario acima, com as variáveis e seus conteúdos.
O mesmo que locals() faz para um namespace local, globals() faz para o namespace global.

>>> import locais
>>> globals()
{'__builtins__': module '__builtin__' (built-in), '__name__': '__main__', '__doc__': None, 'locais': module 'locais' from 'locais.py'}

Vamos entender o que foi feito acima, direto da linha de comando. Primeiro eu importei o módulo criado acima,chamado de locais.py, que contém o exemplo de locals(). Depois, eu chamei a função globals() e ela me retornou o dicionário acima.
'__builtins__', como eu já citei, é o módulo que contém todas as funções, excessões embutidas, o que forma o namespace embutido.
'__name__' funciona da seguinte maneira. Ao rodar um módulo, ao invés de importá-lo, o valor embutido __name__ será __main__. E como nós estamos da linha de comando, __name__ é __main__
E observe também a presença do módulo que foi importadom 'locais', ao ser importado ele pertence ao namespace global.
'__doc__': None, mostra que nosso módulo corrente não tem nenhuma docstring

Uma utilidade para essas funções é a formatação de string com dicionários, eu falei um pouco disso no post anterior sobre dicionários.

Fonte:
- Livro Mergulhando no Python
- Python tutorial

quarta-feira, fevereiro 07, 2007

Argumentos Opcionais

Python nos permite dar valores padrões para argumentos de funções, assim caso tal argumento não seja definido, será usado seu valor padrão, tornando esse argumento opcional.
Para fazer isso, devemos nomear os argumentos que terão seu valor padrão:

>>> def info(nome, idade=18, curso='python'):

Pronto, a função 'info' acima, possui 3 argumentos, 'nome' é um argumento obrigatório, já 'idade' e 'curso' têm valores padrão '18' e 'python' respectivamente.

>>> info('igor') ## 1
>>> info('igor', 20) ## 2
>>> info('igor', curso='plone') ## 3
>>> info(nome='igor', idade=20) ## 4

Vamos analisar as chamadas acima:

## 1: Nesse caso, entramos somente com o argumento obrigatório, então tando 'idade' quanto 'curso' assumem seus valores padrão, '18' e 'python'

## 2: Agora definimos, além do argumento obrigatório, 'idade', que agora passa a ser '20', e seu valor padrão é ignorado. E 'curso' continua com seu valor padrão.

## 3: Mas e se eu quiser definir o argumeto opcional 'curso' mas usar o valor padrão para 'idade'? Simples. Nesse caso nós, fizemos isso, definimos o argumento obrigatório, e também o argumento opcional 'curso' como 'plone'. Deixando 'idade' com seu valor padrão.

## 4: Esse caso é so para mostrar que os argumentos obrigatórios também poder ser nomeados na hora da atribuição.

terça-feira, fevereiro 06, 2007

Funções lambda

Se você precisa de uma função para fazer algo simples, de apenas uma expressão, existe uma maneira bem prática pra fazer isso em Python, usando uma função lamba.
Elas funcionam como uma função normal, só que possuem uma unica linha.

>>> def f(x):
... return x*2
>>> f(3)
6

usando uma função lambda:

>>> f = lambda x: x*2
>>> f(3)
6

Também podemos usar uma função lambda sem atribuí-la a nenhuma variável

>>> (lambda y: y*3 )(2)
6

As funções lambda são sempre opcionais, tudo que fazemos com ela pode ser feito com uma função normal.