¿Es posible modificar una variable en Python que está en un alcance externo (cerrado), pero no global?

Resuelto grigoryvp asked hace 13 años • 9 respuestas

Considere este ejemplo:

def A():
    b = 1
    def B():
        # I can access 'b' from here.
        print(b)
        # But can i modify 'b' here?
    B()
A()

Para el código de la Bfunción, la variable bestá en un ámbito envolvente (externo) no global. ¿ Cómo puedo modificar bdesde dentro B? Obtengo un UnboundLocalErrorsi lo intento directamente y usarlo globalno soluciona el problema ya que bno es global.


Python implementa un alcance léxico, no dinámico , como casi todos los lenguajes modernos. Las técnicas aquí no permitirán el acceso a las variables de la persona que llama, a menos que la persona que llama también sea una función adjunta, porque la persona que llama no está dentro del alcance. Para obtener más información sobre este problema, consulte ¿Cómo puedo acceder a las variables de la persona que llama, incluso si no es un alcance cerrado (es decir, implementar un alcance dinámico)? .

grigoryvp avatar Dec 09 '11 22:12 grigoryvp
Aceptado

En Python 3 , use la nonlocalpalabra clave :

La nonlocaldeclaración hace que los identificadores enumerados hagan referencia a variables previamente vinculadas en el ámbito adjunto más cercano, excluyendo los globales. Esto es importante porque el comportamiento predeterminado para el enlace es buscar primero en el espacio de nombres local. La declaración permite que el código encapsulado vuelva a vincular variables fuera del alcance local además del alcance global (módulo).

def foo():
    a = 1
    def bar():
        nonlocal a
        a = 2
    bar()
    print(a)  # Output: 2

En Python 2 , use un objeto mutable (como una lista o dict) y mute el valor en lugar de reasignar una variable:

def foo():
    a = []
    def bar():
        a.append(1)
    bar()
    bar()
    print a

foo()

Salidas:

[1, 1]
Adam Wagner avatar Dec 09 '2011 15:12 Adam Wagner

Puede utilizar una clase vacía para contener un ámbito temporal. Es como el mutable pero un poco más bonito.

def outer_fn():
   class FnScope:
     b = 5
     c = 6
   def inner_fn():
      FnScope.b += 1
      FnScope.c += FnScope.b
   inner_fn()
   inner_fn()
   inner_fn()

Esto produce el siguiente resultado interactivo:

>>> outer_fn()
8 27
>>> fs = FnScope()
NameError: name 'FnScope' is not defined
chrisk avatar Feb 10 '2014 21:02 chrisk