Buscar..


Sintaxis

  • global a, b, c
  • no local a, b
  • x = algo # se une a x
  • (x, y) = algo # une x y y
  • x + = algo # se une a x. Del mismo modo para todos los demás "op ="
  • del x # se une a x
  • para x en algo: # se une a x
  • con algo como x: # une x
  • excepto Excepción como ex: # binds ex inside block

Variables globales

En Python, las variables dentro de las funciones se consideran locales si y solo si aparecen en el lado izquierdo de una instrucción de asignación, o alguna otra ocurrencia de enlace; de lo contrario, tal enlace se busca en las funciones adjuntas, hasta el alcance global. Esto es cierto incluso si la instrucción de asignación nunca se ejecuta.

x = 'Hi'

def read_x():
    print(x)   # x is just referenced, therefore assumed global

read_x()       # prints Hi

def read_y():
    print(y)   # here y is just referenced, therefore assumed global

read_y()       # NameError: global name 'y' is not defined

def read_y():
    y = 'Hey'  # y appears in an assignment, therefore it's local
    print(y)   # will find the local y

read_y()       # prints Hey

def read_x_local_fail():
    if False:
        x = 'Hey'  # x appears in an assignment, therefore it's local
    print(x)   # will look for the _local_ z, which is not assigned, and will not be found

read_x_local_fail()   # UnboundLocalError: local variable 'x' referenced before assignment

Normalmente, una asignación dentro de un ámbito sombreará las variables externas del mismo nombre:

x = 'Hi'

def change_local_x():
    x = 'Bye'
    print(x)
change_local_x()  # prints Bye
print(x)  # prints Hi

Declarar un nombre global significa que, para el resto del alcance, cualquier asignación al nombre ocurrirá en el nivel superior del módulo:

x = 'Hi'

def change_global_x():
    global x
    x = 'Bye'
    print(x)

change_global_x()  # prints Bye
print(x)  # prints Bye

La palabra clave global significa que las asignaciones se realizarán en el nivel superior del módulo, no en el nivel superior del programa. Otros módulos seguirán necesitando el acceso puntual habitual a las variables dentro del módulo.

Para resumir: para saber si una variable x es local a una función, debe leer la función completa :

  1. Si has encontrado global x , entonces x es una variable global
  2. Si ha encontrado nonlocal x , entonces x pertenece a una función que lo encierra, y no es local ni global
  3. Si ha encontrado x = 5 o for x in range(3) o algún otro enlace, entonces x es una variable local
  4. De lo contrario, x pertenece a algún ámbito adjunto (ámbito de función, ámbito global o elementos incorporados)

Variables locales

Si un nombre está enlazado dentro de una función, por defecto es accesible solo dentro de la función:

def foo():
    a = 5
    print(a) # ok

print(a) #  NameError: name 'a' is not defined

Las construcciones de flujo de control no tienen impacto en el alcance (con la excepción de except ), pero el acceso a la variable que aún no se asignó es un error:

def foo():
    if True: 
        a = 5
    print(a) # ok

b = 3
def bar():
    if False:
        b = 5
    print(b) # UnboundLocalError: local variable 'b' referenced before assignment

Las operaciones de enlace comunes son asignaciones, for bucles y asignaciones aumentadas, como a += 5

Variables no locales

Python 3.x 3.0

Python 3 agregó una nueva palabra clave llamada no local . La palabra clave no local agrega una anulación de ámbito al ámbito interno. Puedes leer todo sobre esto en PEP 3104 . Esto se ilustra mejor con un par de ejemplos de código. Uno de los ejemplos más comunes es crear una función que puede incrementar:

def counter():
    num = 0
    def incrementer():
        num += 1
        return num
    return incrementer

Si intenta ejecutar este código, recibirá un UnboundLocalError porque se hace referencia a la variable num antes de que se asigne en la función más interna. Añadamos nonlocal a la mezcla:

def counter():
    num = 0
    def incrementer():
        nonlocal num
        num += 1
        return num
    return incrementer

c = counter()
c() # = 1
c() # = 2
c() # = 3

Básicamente, nonlocal le permitirá asignar variables en un ámbito externo, pero no global. Por lo tanto, no puede usar el modo no nonlocal en nuestra función de counter porque entonces intentaría asignarlo a un alcance global. SyntaxError y obtendrá rápidamente un SyntaxError . En su lugar, debe utilizar nonlocal en una función anidada.

(Tenga en cuenta que la funcionalidad que se presenta aquí se implementa mejor utilizando generadores).

Ocurrencia vinculante

x = 5
x += 7
for x in iterable: pass    

Cada una de las afirmaciones anteriores es una ocurrencia de enlace : x se une al objeto denotado por 5 . Si esta declaración aparece dentro de una función, entonces x será función local de forma predeterminada. Consulte la sección "Sintaxis" para obtener una lista de declaraciones vinculantes.

Las funciones omiten el alcance de la clase al buscar nombres

Las clases tienen un alcance local durante la definición, pero las funciones dentro de la clase no usan ese alcance cuando buscan nombres. Debido a que las lambdas son funciones, y las comprensiones se implementan utilizando el alcance de la función, esto puede llevar a un comportamiento sorprendente.

a = 'global'

class Fred:
    a = 'class'  # class scope
    b = (a for i in range(10))  # function scope
    c = [a for i in range(10)]  # function scope
    d = a  # class scope
    e = lambda: a  # function scope
    f = lambda a=a: a  # default argument uses class scope
    
    @staticmethod  # or @classmethod, or regular instance method
    def g():  # function scope
        return a

print(Fred.a)  # class
print(next(Fred.b))  # global
print(Fred.c[0])  # class in Python 2, global in Python 3
print(Fred.d)  # class
print(Fred.e())  # global
print(Fred.f())  # class
print(Fred.g()) # global

Los usuarios que no estén familiarizados con el funcionamiento de este ámbito pueden esperar que b , c y e impriman la class .


Desde PEP 227 :

Los nombres en el alcance de la clase no son accesibles. Los nombres se resuelven en el ámbito de la función de cierre más interno. Si una definición de clase se produce en una cadena de ámbitos anidados, el proceso de resolución omite las definiciones de clase.

De la documentación de Python sobre denominación y encuadernación :

El alcance de los nombres definidos en un bloque de clase se limita al bloque de clase; no se extiende a los bloques de código de los métodos; esto incluye comprensiones y expresiones generadoras, ya que se implementan utilizando un ámbito de función. Esto significa que lo siguiente fallará:

class A:
    a = 42
    b = list(a + i for i in range(10))

Este ejemplo utiliza referencias de esta respuesta de Martijn Pieters, que contiene un análisis más profundo de este comportamiento.

El comando del

Este comando tiene varias formas relacionadas pero distintas.

del v

Si v es una variable, el comando del v elimina la variable de su alcance. Por ejemplo:

x = 5
print(x) # out: 5
del x
print(x) # NameError: name 'f' is not defined

Tenga en cuenta que del es una ocurrencia de enlace , lo que significa que a menos que se establezca explícitamente lo contrario (utilizando nonlocal o global ), del v hará que v local al alcance actual. Si pretende eliminar v en un ámbito externo, use nonlocal v o global v en el mismo ámbito de la declaración del v .

En todo lo siguiente, la intención de un comando es un comportamiento predeterminado, pero el idioma no lo impone. Una clase puede estar escrita de una manera que invalida esta intención.

del v.name

Este comando activa una llamada a v.__delattr__(name) .

La intención es hacer que el name del atributo no esté disponible. Por ejemplo:

class A:
    pass

a = A()
a.x = 7
print(a.x) # out: 7
del a.x
print(a.x) # error: AttributeError: 'A' object has no attribute 'x'

del v[item]

Este comando activa una llamada a v.__delitem__(item) .

La intención es que el item no pertenezca a la asignación implementada por el objeto v . Por ejemplo:

x = {'a': 1, 'b': 2}
del x['a']
print(x) #  out: {'b': 2}
print(x['a']) # error: KeyError: 'a'

del v[a:b]

Esto realmente llama v.__delslice__(a, b) .

La intención es similar a la descrita anteriormente, pero con cortes: rangos de elementos en lugar de un solo elemento. Por ejemplo:

x = [0, 1, 2, 3, 4]
del x[1:3]
print(x) #  out: [0, 3, 4]

Véase también Recolección de basura # El comando del .

Ámbito local vs global

¿Cuáles son el alcance local y global?

Todos los variabes de Python a los que se puede acceder en algún punto del código se encuentran en el ámbito local o global .

La explicación es que el alcance local incluye todas las variables definidas en la función actual y el alcance global incluye variables definidas fuera de la función actual.

foo = 1  # global

def func():
    bar = 2  # local
    print(foo)  # prints variable foo from global scope
    print(bar)  # prints variable bar from local scope

Uno puede inspeccionar qué variables están en qué alcance. Las funciones integradas locals() y globals() devuelven todos los ámbitos como diccionarios.

foo = 1

def func():
    bar = 2
    print(globals().keys())  # prints all variable names in global scope
    print(locals().keys())  # prints all variable names in local scope

¿Qué pasa con los choques de nombre?

foo = 1

def func():
    foo = 2  # creates a new variable foo in local scope, global foo is not affected

    print(foo)  # prints 2

    # global variable foo still exists, unchanged:
    print(globals()['foo'])  # prints 1
    print(locals()['foo'])  # prints 2

Para modificar una variable global, use la palabra clave global :

foo = 1

def func():
    global foo
    foo = 2  # this modifies the global foo, rather than creating a local variable

El alcance se define para todo el cuerpo de la función!

Lo que significa es que una variable nunca será global para la mitad de la función y local después, o viceversa.

foo = 1

def func():
    # This function has a local variable foo, because it is defined down below.
    # So, foo is local from this point. Global foo is hidden.

    print(foo) # raises UnboundLocalError, because local foo is not yet initialized
    foo = 7
    print(foo)

Asimismo, el opuesto:

foo = 1

def func():
    # In this function, foo is a global variable from the begining

    foo = 7  # global foo is modified

    print(foo)  # 7
    print(globals()['foo'])  # 7

    global foo  # this could be anywhere within the function
    print(foo)  # 7

Funciones dentro de funciones

Puede haber muchos niveles de funciones anidadas dentro de las funciones, pero dentro de una función solo hay un ámbito local para esa función y el ámbito global. No hay ámbitos intermedios.

foo = 1

def f1():
    bar = 1

    def f2():
        baz = 2
        # here, foo is a global variable, baz is a local variable
        # bar is not in either scope
        print(locals().keys())  # ['baz']
        print('bar' in locals())  # False
        print('bar' in globals())  # False

    def f3():
        baz = 3
        print(bar)  # bar from f1 is referenced so it enters local scope of f3 (closure)
        print(locals().keys())  # ['bar', 'baz']
        print('bar' in locals())  # True
        print('bar' in globals())  # False

    def f4():
        bar = 4  # a new local bar which hides bar from local scope of f1
        baz = 4
        print(bar)
        print(locals().keys())  # ['bar', 'baz']
        print('bar' in locals())  # True
        print('bar' in globals())  # False

global vs nonlocal (solo Python 3)

Estas dos palabras clave se utilizan para obtener acceso de escritura a variables que no son locales a las funciones actuales.

La palabra clave global declara que un nombre debe tratarse como una variable global.

foo = 0  # global foo

def f1():
    foo = 1  # a new foo local in f1
    
    def f2():
        foo = 2  # a new foo local in f2
        
        def f3():
            foo = 3  # a new foo local in f3
            print(foo)  # 3
            foo = 30  # modifies local foo in f3 only
        
        def f4():
            global foo
            print(foo)  # 0
            foo = 100  # modifies global foo

Por otro lado, nonlocal (consulte Variables no locales ), disponible en Python 3, toma una variable local de un ámbito de inclusión en el ámbito local de la función actual.

De la documentación de Python en nonlocal :

La declaración no local hace que los identificadores enumerados se refieran a variables previamente vinculadas en el ámbito envolvente más cercano, excluyendo las globales.

Python 3.x 3.0
def f1():
    
    def f2():
        foo = 2  # a new foo local in f2

        def f3():
            nonlocal foo  # foo from f2, which is the nearest enclosing scope
            print(foo)  # 2
            foo = 20  # modifies foo from f2!


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow