Baixe o app para aproveitar ainda mais
Prévia do material em texto
Nomes, Espaços de Nomes e Escopos em Python (Miguel Jonathan, set 2009) Geral Todos os métodos são virtuais (no sentido de C++), ou seja, ligados (link-editados) em tempo de execução. Todos os métodos de instância devem ter self como primeiro argumento. Todos os tipos de dados são objetos. Operadores podem ser redefinidos em classes. Nomes são ligados a objetos (por referência). Múltiplos nomes, em diversos contextos, podem ser ligados ao mesmo objeto (aliasing) Atributos em Python Todos os atributos de uma classe são públicos. Atributos é qualquer nome após um ponto em uma expressão (variáveis e métodos ou funções). Funções em módulos são atributos do módulo: <nome-módulo>. <nome-função>(). Criação, alteração e remoção de atributos: Atributos podem ser inalteráveis (read-only) ou alteráveis (writeable). Atributos alteráveis podem receber atribuição de valor, em expressões do tipo atributo = expressão. Atributos alteráveis podem também ser removidos com o comando del. Por exemplo: del o.x removerá o atributo x do objeto referenciado por o. Regras sobre espaços de nomes e escopos. Um "espaço de nomes" (namespace) é um mapa (normalmente implementado com dicionário) que associa nomes a objetos. Não existe nenhuma relação entre nomes utilizados em espaços de nomes diferentes. Por esse motivo, um mesmo nome pode existir em espaços diferentes, sem que haja conflito. Um "escopo" (scope) é uma região de texto em um programa Python onde um determinado espaço de nomes é acessível diretamente (sem prefixos). Um nome usado sem prefixo é também chamado de "referência não qualificada". Existem diversos espaços de nomes, cada um com tempo de vida próprio: - Os nomes pré-definidos (built-in): esse espaço é criado quando o interpretador Python inicia, e é nunca removido. Fazem parte do módulo __builtin__. Exemplo: a função abs(). - Os nomes globais de um módulo: esse espaço é criado quando o módulo é lido, e em geral permanece também até o interpretador sair. - Em particular, os nomes do módulo __main__, que estão contidos nos comandos executados no nível mais alto de invocação do interpretador, seja em comandos interativos, seja em comandos lidos de um arquivo de script (,py), fora de qualquer função. - Os nomes locais durante uma chamada de função: esse espaço é criado quando a função é chamada, e removido quando a função retorna ou lança uma exceção que não é tratada dentro da função. Inclui os parâmetros da função. - Chamadas recursivas de uma mesma função possuem, cada uma, o seu próprio espaço de nomes. - O conjunto dos atributos de um objeto constitui um espaço de nomes. Em módulos, os nomes globais e os atributos do módulo partilham o mesmo espaço de nomes. Aninhamento de escopos em tempo de execução: A qualquer momento, durante a execução de um programa ou função Python, existem pelo menos três escopos aninhados cujos espaços de nomes são acessíveis diretamente (i.e., sem necessidade de prefixo com ponto) para encontrar um nome. Esses espaços são pesquisados em uma determinada ordem: primeiramente, o nome é procurado no escopo mais interno, local e nos espaços de nomes das funções envolvendo o escopo onde o nome aparece. A seguir, no escopo dos nomes globais do módulo. Finalmente, no escopo dos nomes pré-definidos (built-in). Isso significa que um nome global, ou pré-definido na linguagem, pode ser substituído por um nome local. Por exemplo: abs(x) é uma função pré-definida, que retorna o valor absoluto de um número x. Mas se fizermos, em um módulo: def abs(x): return x*x o nome abs passará a existir localmente com esse novo significado. Nesse módulo, a chamada abs(-9) retornará 81. Se, a seguir, executarmos, neste módulo, o comando del abs, o nome abs será removido do espaço de nomes local e, a partir desse ponto, qualquer chamada a abs() voltará a se referir à função abs pré-definida. A declaração global Podemos declarar um ou mais nomes como global, dentro de um escopo local, como por exemplo: global x,y Toda referência e atribuição a esses nomes, de dentro deste escopo local, irão diretamente ao escopo global. Se for feita uma atribuição, e o nome ainda não tiver sido declarado no escopo global, ele será criado no espaço global. Exemplo: def f(): x = 10 # x é local em f() def g(): x = 3 # x é redefinido em g() global y # o nome y será criado globalmente, quando g() for chamada y = 100*x # o valor global y valerá 300. Neste escopo, x vale 3. g() # nesse ponto, y passará a existir globalmente, se não tiver sido criado antes. return x+y # retornará 310, pois x não foi modificado em f(), e continua valendo 10. Depois que a função retornar, o nome y continuará a existir globalmente com valor 300. Caso a declaração global não tiver sido feita, toda atribuição a um nome criará um novo nome local. Mesmo se o mesmo nome existir globalmente, dentro do escopo local valerá o novo nome. Importante: Um nome passa a existir em um escopo local somente após ser atribuído a um valor (com = ), ou por definição de função interna, caso não tenha sido previamente declarado como global nesse escopo. Antes disso, qualquer referência ao nome neste escopo causará uma busca do nome nos escopos mais externos e o primeiro nome a ser encontrado será usado. Por exemplo: y = 200 def f(): print y f() # OK, imprime 200 Mas, se no escopo local for feita uma referência a um nome ainda não definido, e depois disso for feita uma atribuição, haverá um erro, pois o nome será considerado local desde o início, e a primeira referência será considerada inválida. Por exemplo: y = 200 def f(): print y y = 0 # a atribuição faz com que y se torne local a f() f() # Erro de execução. Tentativa de acessar variável local y antes da atribuição de valor Outro exemplo: seja um módulo de nome escopos.py, com o seguinte texto: z = 100 # z, x, f e g estão no espaço de nomes do módulo x = 10 def f(x): # esse é um outro x, um nomel local de f, que recebe um valor inicial na chamada print z # como z não foi redefinido nesse escopo, aqui vale o z do módulo return x*x def g(y): # y é um nome local no espaço da função g. x = y * 2 # um outro nome x, no escopo de g def h(z): # h está no escopo de g. z é um nome definido no escopo de h return z + x # essa soma usará o z de h, e o x do escopo de g print h(y) g(5) #imprime 15 print f(3) #imprime 100, e depois 9 Outro exemplo usando nome global: def f(): def g(): x = 3 # x é redefinido em g() global y # o nome y será criado globalmente, quando g() for chamada y = 100*x # o valor global y valerá 300. Neste escopo, x vale 3. x = 10 # x é local em f() g() # nesse ponto, y passará a existir globalmente return x+y # retornará 310 print f() #imprime 310
Compartilhar