2012-01-31 18 views
10

Tome el siguiente código:"variable local a la que se hace referencia antes de la asignación": ¿solo funciones?

import something 

def Foo(): 
    something = something.SomeClass() 
    return something 

... esto es al parecer código no válido:

UnboundLocalError: local variable 'something' referenced before assignment 

... como la variable local se crea something, pero no asignado, antes de que el lado derecho de la = se evalúa . (Ver, por ejemplo, this related answer's comment.) Esto me parece un poco extraño, pero claro, lo haré. Ahora, ¿por qué es el siguiente código válido?

class Foo(object): 
    something = something.SomeClass() 

Mi entendimiento es que el interior de una definición class era esencialmente un ámbito de aplicación:

conjunto de la clase se ejecuta entonces en un nuevo marco de ejecución (véase la sección de nombres y vinculante), utilizando una nueva espacio de nombres local creado y el espacio de nombres global original.

Entonces, ¿por qué ese código actúa de forma diferente a la de una función?

+0

'something' parece tener más de un significado? – Johnsyweb

+0

@Johnsyweb: Sí, tipo de. Pero en ambos casos, tiene el mismo tipo de más de un significado. (O, al menos, todos los documentos que he leído parecen decir eso). – Thanatos

Respuesta

4

consideremos el siguiente ejemplo que puede ayudar a aclarar esto:

import datetime 

class Foo(object): 
    datetime = datetime.datetime 

>>> datetime 
<module 'datetime' from '/usr/lib/python2.6/lib-dynload/datetime.so'> 
>>> Foo.datetime 
<type 'datetime.datetime'> 

Tenga en cuenta que la línea datetime = datetime.datetime es en realidad asignando al nombre Foo.datetime, que no es ambigua con el mundial datetime (como sería si el el mismo código estaba en la función).

En resumen, dado que las definiciones de clase crean un nuevo espacio de nombres además de un nuevo ámbito, se le permite acceder directamente a un nombre en un ámbito adjunto y asignarlo al mismo nombre en el ámbito local.

+0

"Tenga en cuenta que la línea' datetime = datetime.datetime' en realidad está asignando el nombre 'Foo '.datetime', que no es ambiguo con el 'datetime' global -" No: está asignando al nombre 'datetime': Si agrega dos sentencias' print datetime', una antes de 'datetime =', y una después, cómo es el 'datetime' en esa declaración * no * ambiguo, de alguna manera que es diferente de las mismas declaraciones en una función? – Thanatos

+0

@Thanatos - Sí, puedo ver cómo no está claro. Lo que estaba tratando de decir es que el espacio de nombres creado por la clase permite una forma inequívoca de acceder al atributo global y de clase desde otros ámbitos, pero todavía hay ambigüedad dentro del alcance local de la clase. –

+0

Pero el quid de la cuestión es ¿cómo es esto diferente? ¿Qué sucede en una función? Usted declara, "porque las definiciones de clase crean un nuevo espacio de nombres además de un nuevo ámbito" - ¿las funciones no crean un nuevo espacio de nombre y un nuevo ámbito? - "se le permite acceder directamente a un nombre en un alcance adjunto "- Puedo hacer esto en una función - "y asignar al mismo nombre en el ámbito local" - Solo puedo hacer esto en una definición de clase ... ¿por qué? – Thanatos

6

Desde el python class documentation:

Las definiciones de clases lugar otro espacio de nombres en el ámbito local.

Una peculiaridad especial de Python es que, si no hay ninguna declaración global vigente, las asignaciones a los nombres siempre van al ámbito más interno. Las asignaciones no copian datos, solo vinculan nombres a objetos. Lo mismo es cierto para las eliminaciones: la sentencia del x elimina la vinculación de x del espacio de nombres al que hace referencia el alcance local. De hecho, todas las operaciones que introducen nombres nuevos usan el ámbito local: en particular, las sentencias de importación y las definiciones de funciones vinculan el nombre del módulo o la función en el ámbito local. (La declaración global puede ser utilizado para indicar que ciertas variables viven en el ámbito global.)

Así que dentro de una función (o un ámbito de aplicación) la asignación crea una variable no ligada local que se accede antes de que está obligado, mientras en una definición de clase crea una entrada en el diccionario "espacio de nombres" de esa clase en la asignación, lo que permite la resolución de something en el espacio de nombres externo (el espacio de nombres del módulo).

Cuestiones relacionadas