[Curso de Python] Escopo de Variáveis Parte 1
31 de Agosto de 2010, 0:00 - sem comentários aindaAntes de prosseguir leia os artigos anteriores aqui
Olá pessoal! Agora estamos entrando em um assunto muito mais "pesado". Vamos logo ao conteúdo!
Escopo de Variáveis Parte 1
Inicialmente vamos entender o que é escopo. Escopo é o mesmo que extensão, alcance, âmbito e/ou competência. Dessa forma o escopo de uma variável é a "área" na qual ela pode ser utilizada.
O Python tem 3 escopos principais:
- locais;
- globais;
- built-ins.
O escopo mais simples de se entender é o global. Existe um e apenas um escopo global. Você pode consultar o escopo global do seu programa usando a função globlas():
A função globals() retorna um dicionário contendo diversos itens. Como o dicionário é composto por chaves e valores ele nos apresenta o nome do item e o seu respectivo valor. Para facilitar a visualização, vou usar um método do dicionário que imprime somente suas chaves, o método keys():Código:>>> globals() {'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__d oc__': None, '__package__': None}
Como podemos ver o nosso escopo global apresenta 4 "itens" que sempre estarão presentes: __builtins__, __main__, __doc__ e __package__.Código:>>> globals().keys() ['__builtins__', '__package__', '__name__', '__doc__'] >>>
No momento não vou me ater a explicar o que seriam esses nomes pois eles serão entendidos à medida que vemos outros conteúdos, vamos focar no momento no que o globals representa, para isso vou mostrar um outro exemplo:
Conforme apresentado, a função globals() agora apresenta as variáveis criadas (x, texto e lista). Podemos ver que o nome das variáveis são as chaves dos dicionários enquanto os valores das variáveis são os itens vinculados às chaves. Com isso podemos "chamar" as variáveis utilizando o dicionário:Código:>>> globals().keys() ['__builtins__', '__name__', '__doc__', '__package__'] >>> x = 12 >>> texto = 'teste' >>> lista = [1, 2, 3] >>> globals().keys() ['__builtins__', 'texto', '__package__', 'x', '__name__', 'lista', '__doc__'] >>> globals() {'__builtins__': <module '__builtin__' (built-in)>, 'texto': 'teste', '__package __': None, 'x': 12, '__name__': '__main__', 'lista': [1, 2, 3], '__doc__': None} >>>
Claro, isso não tem utilidade nenhuma para nós no momento, mas é sempre bom ressaltar as possibilidades. Vamos criar agora algumas funções:Código:>>> globals()['x'] 12 >>> globals()['texto'] 'teste' >>> globals()['lista'] [1, 2, 3] >>>
Podemos ver que o comando globals mostra também as funções existentes no programa. Isso pode ser útil caso você precise descobrir se uma dada função já existe no seu programa. Vamos ver como as funções são apresentadas nos itens do dicionário retornado pelo comando globals():Código:>>> def funcao_1(): ... print 'Estou na função 1' ... >>> def funcao_2(): ... print 'Estou na função 2' ... >>> >>> globals().keys() ['funcao_2', '__builtins__', 'texto', '__package__', 'x', '__name__', 'funcao_1' , 'lista', '__doc__'] >>>
Vinculado ao nome da função (por exemplo a funcao_2) temos o endereço de memória que a função está ocupando: <function funcao_2 at 0x00B41130>. Como se pode imaginar, é possível chamar a função dada o seu nome em string:Código:>>> globals() {'funcao_2': <function funcao_2 at 0x00B41130>, '__builtins__': <module '__built in__' (built-in)>, 'texto': 'teste', '__package__': None, 'x': 12, '__name__': ' __main__', 'funcao_1': <function funcao_1 at 0x00B41030>, 'lista': [1, 2, 3], '_ _doc__': None} >>>
Por enquanto vamos parar por aqui e deixar que todos se acostumem com a idéia. Em seguida vamos utilizar essa função para podermos descobrir a "abrangência" de uma função e/ou variável.Código:>>> globals()['funcao_1'] <function funcao_1 at 0x00B41030> >>> globals()['funcao_1']() Estou na função 1 >>>
Até mais...
[Curso de Python] Ultima Palavra Sobre Argumentos de Funções
23 de Agosto de 2010, 0:00 - sem comentários aindaAntes de prosseguir leia os artigos anteriores aqui
Olé pessoal! Estamos de volta com mais uma aula deste curso de introdução ao Python. Nesse post vou falar basicamente sobre alguns detalhes relevantes às variáveis utilizadas nos argumentos de funções.
Ultima Palavra Sobre Argumentos de Funções
Quando trabalhamos com argumentos de funções começamos a entrar em dúvida sobre as variáveis utilizadas. Então vamos ressaltar alguns comportamentos e dicas sobre os argumentos de funções.
1. Primeiro ponto a ressaltar é que a função do argumento não precisa ter o mesmo nome que a variável do argumento. Pode parecer lógico mas este tipo de dúvida ocorre:
2. A variável passada para função é a mesma utilizada dentro da função. Complicou?! Olhando o exemplo acima, a variável var1 passada para a função teste é a mesma variável f_var1. Quer uma prova disso? Basta usar a função id:Código:>>> def teste(f_var1): ... print f_var1 ... >>> var1 = 12 >>> var2 = 20 >>> teste(var1) 12 >>> teste(var2) 20 >>>
Como podemos ver, a variável é sempre a mesma. Agora vamos fazer uma pequena brincadeira:Código:>>> def teste_id(var): ... print 'Identificador na função:',id(var) ... >>> var1 = 'teste1' >>> print 'Identificador global:',id(var1) Identificador global: 3078433056 >>> teste_id(var1) Identificador na função: 3078433056 >>> var2 = [1, 2, 3] >>> print 'Identificador global:',id(var2) Identificador global: 3078433568 >>> teste_id(var2) Identificador na função: 3078433568 >>>
Se a variável é sempre a mesma, então porque quando alteramos o valor da variável texto a outra variável texto1 não se alterou?. Essa é uma explicação simples mas complexa, se é que isso é possível. Em Python, conforme já havíamos comentado, os tipos (int, float, list, tuple e etc) podem ser classificados em 2 tipos: mutáveis e imutáveis. Os tipos mutáveis são aqueles que podem ser alterados como listas e dicionários, enquanto os imutáveis são queles que seus valores não podem ser alterados, inteiros, complexos, longos, ponto flutuante, tuplas e booleanos. Quando tentamos alterar o valor de um tipo imutável, o que realmente ocorre é a criação de uma nova variável.Código:>>> def altera_texto(texto): ... texto = '(' + texto + ')' ... print 'texto em funcao:',texto ... >>> texto1 = 'teste' >>> altera_texto(texto1) texto em funcao: (teste) >>> print 'texto global:',texto1 texto global: teste >>>
As variáveis em Python funcionam como ponteiros, elas apontam para uma posição de memoria, inclusive o número mostrado pela função id, é o endereço de memória daquela variável. Quando fazemos x = 1, criamos o valor estático 1 e apontamos para ela a variável x. Quanto fazemos x = 2, o valor 1 é descartado e o valor 2 é criado, x passa a apontar para essa nova posição de memoria.
Ok, então vamos ver agora como o Python se comporta quando alteramos valores de tipos mutáveis, neste exemplo utilizarei o método append das listas. Esse método adiciona um novo item:
Como podemos ver, ambas as variáveis foram alteradas. Isso ocorre porque não temos re-atribuição de variável apenas alteramos a variável existente.Código:>>> def altera_lista(lista): ... lista.append('novo item') ... print 'lista da função:',lista ... >>> lista1 = ['item', 'outro item'] >>> altera_lista(lista1) lista da função: ['item', 'outro item', 'novo item'] >>> print 'lista global:',lista1 lista global: ['item', 'outro item', 'novo item'] >>>
3. Variáveis criadas dentro de funções não podem ser acessadas externamente. Isso ocorre devido ao escopo de variáveis que será explicado com detalhes mais a frente. Vamos ao exemplo:
4. Argumentos pre-definidos podem ter dar dor de cabeça. Só tem uma forma de explicar isso, através de um exemplo:Código:>>> def teste(var): ... valor = var + 10 ... >>> teste(10) >>> print valor Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'valor' is not defined >>>
A primeira chamada (altera_lista([1, 2, 3])) não nos surpreende e retorna sempre o valor esperado, a lista passada como argumento com um novo item (o valor 10). á as execuções utilizando o argumento padrão (com exceção da primeira chamada) está completamente o oposto do que deveria ser. Isto ocorre pois a variável padrão é iniciada apenas no início do programa, e toda vez que a alteramos este valor é armazenado para a próxima execução. O melhor modo de ter o comportamento esperado é inciar uma nova lista, da seguinte forma:Código:>>> def altera_lista(lista=[4, 5, 6]): ... lista.append(10) ... print lista ... >>> altera_lista([1, 2, 3]) [1, 2, 3, 10] >>> altera_lista([1, 2, 3]) [1, 2, 3, 10] >>> altera_lista([1, 2, 3]) [1, 2, 3, 10] >>> >>> altera_lista() [4, 5, 6, 10] >>> altera_lista() [4, 5, 6, 10, 10] >>> altera_lista() [4, 5, 6, 10, 10, 10] >>>
O lista[:] está simplesmente criando uma cópia da lista e atribuíndo-a para a variável lista. Durante essa execução esse será o valor de lista, quando a função for chamada novamente ela "apontará" a variável lista de volta para o valor padrão de [4, 5, 6].Código:>>> def altera_lista(lista=[4, 5, 6]): ... lista = lista[:] ... lista.append(10) ... print lista ... >>> altera_lista() [4, 5, 6, 10] >>> altera_lista() [4, 5, 6, 10] >>> altera_lista() [4, 5, 6, 10] >>>
Não se esqueçam que as variáveis em Python são meros ponteiros, com isso em mente será mais fácil entender e prever esse tipo de comportamento.
Até a próxima...
Repercussão do Curso de Python
18 de Agosto de 2010, 0:00 - sem comentários aindaEditar um curso dentro da comunidade Under-Linux é muito legal. Vejo a resposta de diversas pessoas que acompanho o curso e me sinto "gratificado" por saber que estou ajudando tanta gente e por ver que tantas pessoas estão interessadas no que escrevo.
Apesar do tamanho da nossa comunidade ela não se compara com o resto da internet, por isso me senti muito muito "gratificado" esses dias quando recebi um link do Sérgio Berloto, do blog Programando Python no RS. Para quem quiser ver o comentário dele a cerca do Curso de Python o link está aqui: Curso de Pyhon - Programando Python no RS
Não sei em que circunstâncias ele caiu aqui (provavelmente) pelo Google mas se ele me linkou é porque eu devo ter quebrado um galho pra ele :). Então estou retribuindo o favor...
Então quem gosta de Python e principalmente Django, vale a pena conferir esse blog pois tem muito conteúdo interessante, além do cara ser apreciador de Heavy Metal, o que já o fez ganhar um leitor através do GoogleReader :D.
Update: Acabei de ver que o cara ta editando um livro gratúito sobre ArchLinux!
Até mais...
[Curso de Python] Funções que Retornam Valores - Parte 2/2
18 de Agosto de 2010, 0:00 - sem comentários aindaAntes de prosseguir leia os artigos anteriores aqui
Olá pessoal! Hoje não tem muito blah blah blah, vamos fechar o conceito do "comando" return para podermos ver conceitos mais avançados com as funções em Python.
Funções que Retornam Valores - Parte 2/2
Conformefalamos na última aula, o comando return pode retornar qualquer tipo de dados. Diferente de outras linguagens o Python não restringe o tipo da variável de retorno, como ocorre em linguagens como C/C++, Java e etc. Vamos a um exemplo simples:
Como mostrado acima, uma única função pode retornar diversos diversos tipos diferentes.Código:>>> def retorna(tipo): ... if tipo == 'int': ... return 1 ... elif tipo == 'long': ... return 1L ... elif tipo == 'float': ... return 1.5 ... elif tipo == 'complex': ... return 1 + 2j ... elif tipo == 'list': ... return [1,2,3] ... elif tipo == 'tuple': ... return (1,2,3) ... elif tipo == 'dict': ... return {'a':1, 'b':2} ... >>> >>> retorna('int') 1 >>> retorna('long') 1L >>> retorna('float') 1.5 >>> retorna('complex') (1+2j) >>> retorna('list') [1, 2, 3] >>> retorna('tuple') (1, 2, 3) >>> retorna('dict') {'a': 1, 'b': 2} >>>
Muitas pessoas se espantam quando vêem códigos em Python que retornam mais de uma variável. Devido à maleabilidade do Python, você pode fazer códigos estranhos como esse:
Quando olhamos rapidamente o código acima temos q impressão de que o comando return no Python é capaz de retornar mais de uma variável (nesse exemplo o booleano True e o inteiro 2), mas isso não passa de uma "ilusão" pois quando chamamos a função e passamos o seu valor para uma única variável, vemos que na verdade foi retornado uma tupla com dois valores. Dessa forma, utilizar o "return True, 2" é o mesmo que "return (True, 2)". Pessoalmente prefiro utilizar os parênteses para ficar claro que aquilo é uma tupla, não correndo o risco de gerar uma dupla interpretação sobre o código.Código:>>> def teste(): ... return True, 2 ... >>> flag, numero = teste() >>> flag True >>> numero 2 >>> x = teste() >>> print x (True, 2) >>> type(x) <type 'tuple'> >>>
Até a próxima pessoal...
[Curso de Python] Funções que Retornam Valores - Parte 1/2
11 de Agosto de 2010, 0:00 - sem comentários aindaAntes de prosseguir leia os artigos anteriores aqui
Olá pessoal! Revendo algumas das nossas últimas aulas sobre funções percebi que havia esquecido de abordar o assunto de funções que retornam valores. Então vamos voltar um pouco nos conceitos mais avançados de funções e vamos ver um conceito mais básico, o "comando" return.
Funções que Retornam Valores - Parte 1/2
Muitas vezes criamos funções para simplificar e modularizar o nosso código. Muitas dessas organizações consistem em funções que realizam algum processamento que pode vir a ser repetido diversas vezes. O "comando" return torna possível que uma função retorne um valor. Esse valor pode ser útil para uma outra parte do programa e pode ser guardado em uma variável. Em Python, não há restrições quanto ao tipo do valor a ser retornado. Vamos a um exemplo básico, uma função que diz se o argumento é uma string ou não. Nesse exemplo, vou utilizar a função type, para quem não lembra como ela funciona vale uma revisão na seguinte aula: [Curso de Python] Comparando os tipos de variáveis
Nesse exemplo, vemos como o return funciona de forma diferente de um "comando" comum. na função eh_str2 utilizamos o print para mostrar o fluxo do programa. Quando o programa entra no if ele imprime 'eh str', depois sai do if e executa o print 'nao eh str'. Já quando utilizamos o return na função eh_str vemos que quando ele entra no if ele nunca sai, pois o comando return quebra toda a execução da função e retorna para o ponto onde a função foi chamada. Vamos ver agora o mesmo exemplo mas com o valor retornado sendo armazenado em uma variável:Código:>>> def eh_str(arg): ... if type(arg) is str: ... return True ... return False ... >>> >>> def eh_str2(arg): ... if type(arg) is str: ... print 'eh str' ... print 'nao eh str' ... >>> >>> eh_str(12) False >>> eh_str('teste') True >>> eh_str([1,2]) False >>> >>> eh_str2(12) nao eh str >>> eh_str2('teste') eh str nao eh str >>> eh_str2([1,2]) nao eh str >>>
Podemos notar que o return "envia" de volta uma variável, nesse caso o booleano True. No caso da função eh_str2, como não retornamos nenhuma variável, por padrão é retornado a variável None, o valor nulo utilizado pelo Python.Código:>>> def eh_str(arg): ... if type(arg) is str: ... return True ... return False ... >>> >>> def eh_str2(arg): ... if type(arg) is str: ... print 'eh str' ... print 'nao eh str' ... >>> >>> ret = eh_str('teste') >>> print ret,type(ret) True <type 'bool'> >>> ret = eh_str2('teste') eh str nao eh str >>> print ret,type(ret) None <type 'NoneType'> >>>
Nesse próximo exemplo, vou utilizar o operador in, para quem não lembra como ele funciona basta consultar essa aula: [Curso de Python] Condições com o operador in
Como podemos ver, no código a função valida texto itera sobre cada letra do texto informado verificando se ela está na variável CARACTERES_VALIDOS. Caso não esteja (if letra not in CARACTERES_VALIDOS) ele retorna o valor falso. O comando return automaticamente sai da função, cancelando toda sua execução, dessa forma ele não itera sobre o restante das letras.Código:# Este programa verifica se o texto # informada possui apenas letras e espaços # Esta variável possui todos os caracteres válidos CARACTERES_VALIDOS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVwXYZ ' def valida_texto(texto): for letra in texto: if letra not in CARACTERES_VALIDOS: return False return True while True: texto = raw_input('Informe um texto (para sair digite "sair"): ') if texto == 'sair': break retorno = valida_texto(texto) if retorno: print 'Texto validado' else: print 'Texto inválido!' print 'Até a próxima...'
Caso ele não entre no if nenhuma vez durante a iteração temos a certeza que todas as letras são válidas, com isso retornamos o valor True. No loop while recebemos o texto com a função raw_input e verificamos se foi digitado 'sair. Caso positivo, saímos do loop com o comando break. Em seguida chamamos a função valida_texto e armazenamos seu retorno na variável 'retorno'. Dependendo do retorno imprimimos uma mensagem para o usuário e no final emitimos a mensagem de finalização do programa. Vamos ver um exemplo de execução:
Nos testes vemos que as frases com acentos, números e qualquer outro caractere que não sejam as letras de a-z e A-Z, será mostrada a mensagem "Texto inválido!".Código:Informe um texto (para sair digite "sair"): este é um teste Texto inválido! Informe um texto (para sair digite "sair"): este eh 1 teste Texto inválido! Informe um texto (para sair digite "sair"): este eh um teste Texto validado Informe um texto (para sair digite "sair"): sair Até a próxima...
Até a próxima...