script que puedo programa hacer evitar ejecutar desde correr consola compilar como cierre archivo abrir python closures

que - no puedo ejecutar python



¿Qué limitaciones tienen los cierres en Python en comparación con los cierres de lenguaje X? (7)

@John Millikin

def outer(): x = 1 # local to `outer()` def inner(): x = 2 # local to `inner()` print(x) x = 3 return x def inner2(): nonlocal x print(x) # local to `outer()` x = 4 # change `x`, it is not local to `inner2()` return x x = 5 # local to `outer()` return (inner, inner2) for inner in outer(): print(inner()) # -> 2 3 5 4

Donde X es cualquier lenguaje de programación (C #, Javascript, Lisp, Perl, Ruby, Scheme, etc.) que admite cierto sabor de cierres.

Algunas limitaciones se mencionan en los cierres en Python (en comparación con los cierres de Ruby), pero el artículo es antiguo y ya no existen muchas limitaciones en el Python moderno.

Ver un ejemplo de código para una limitación concreta sería genial.

Preguntas relacionadas


Corregido en Python 3 a través de la declaración nonlocal :

La declaración nonlocal hace que los identificadores enumerados se refieran a las variables previamente enlazadas en el ámbito circundante más cercano, excluyendo los globales. Esto es importante porque el comportamiento predeterminado para el enlace es buscar primero el espacio de nombres local. La instrucción permite que el código encapsulado vuelva a enlazar variables fuera del alcance local además del alcance global (módulo).


La única dificultad que he visto que las personas encuentran con Python en particular es cuando intentan mezclar características no funcionales como la reasignación de variables con cierres, y se sorprenden cuando esto no funciona:

def outer (): x = 1 def inner (): print x x = 2 return inner outer () ()

Por lo general, señalar que una función tiene sus propias variables locales es suficiente para disuadir tal tontería.


La limitación más importante, actualmente, es que no se puede asignar a una variable de ámbito externo. En otras palabras, los cierres son de solo lectura:

>>> def outer(x): ... def inner_reads(): ... # Will return outer''s ''x''. ... return x ... def inner_writes(y): ... # Will assign to a local ''x'', not the outer ''x'' ... x = y ... def inner_error(y): ... # Will produce an error: ''x'' is local because of the assignment, ... # but we use it before it is assigned to. ... tmp = x ... x = y ... return tmp ... return inner_reads, inner_writes, inner_error ... >>> inner_reads, inner_writes, inner_error = outer(5) >>> inner_reads() 5 >>> inner_writes(10) >>> inner_reads() 5 >>> inner_error(10) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 11, in inner_error UnboundLocalError: local variable ''x'' referenced before assignment

Un nombre que se asigna en un ámbito local (una función) es siempre local, a menos que se indique lo contrario. Si bien existe la declaración "global" para declarar una variable global incluso cuando está asignada a, no existe tal declaración para las variables adjuntas - todavía. En Python 3.0, existe (habrá) la declaración ''no local'' que hace justamente eso.

Puede evitar esta limitación mientras tanto utilizando un tipo de contenedor mutable:

>>> def outer(x): ... x = [x] ... def inner_reads(): ... # Will return outer''s x''s first (and only) element. ... return x[0] ... def inner_writes(y): ... # Will look up outer''s x, then mutate it. ... x[0] = y ... def inner_error(y): ... # Will now work, because ''x'' is not assigned to, just referenced. ... tmp = x[0] ... x[0] = y ... return tmp ... return inner_reads, inner_writes, inner_error ... >>> inner_reads, inner_writes, inner_error = outer(5) >>> inner_reads() 5 >>> inner_writes(10) >>> inner_reads() 10 >>> inner_error(15) 10 >>> inner_reads() 15


La mejor solución hasta 3.0 es incluir la variable como un parámetro predeterminado en la definición de función adjunta:

def f() x = 5 def g(y, z, x=x): x = x + 1


Una limitación (o "limitación") de los cierres de Python, en comparación con los cierres de Javascript, es que no se puede utilizar para ocultar datos de forma efectiva.

Javascript

var mksecretmaker = function(){ var secrets = []; var mksecret = function() { secrets.push(Math.random()) } return mksecret } var secretmaker = mksecretmaker(); secretmaker(); secretmaker() // privately generated secret number list // is practically inaccessible

Pitón

import random def mksecretmaker(): secrets = [] def mksecret(): secrets.append(random.random()) return mksecret secretmaker = mksecretmaker() secretmaker(); secretmaker() # "secrets" are easily accessible, # it''s difficult to hide something in Python: secretmaker.__closure__[0].cell_contents # -> e.g. [0.680752847190161, 0.9068475951742101]


comentario para la respuesta de @Kevin Little para incluir el ejemplo de código

nonlocal no resuelve completamente este problema en python3.0:

x = 0 # global x def outer(): x = 1 # local to `outer` def inner(): global x x = 2 # change global print(x) x = 3 # change global return x def inner2(): ## nonlocal x # can''t use `nonlocal` here print(x) # prints global ## x = 4 # can''t change `x` here return x x = 5 return (inner, inner2) for inner in outer(): print(inner()) # -> 2 3 3 3

Por otra parte:

x = 0 def outer(): x = 1 # local to `outer` def inner(): ## global x x = 2 print(x) # local to `inner` x = 3 return x def inner2(): nonlocal x print(x) x = 4 # local to `outer` return x x = 5 return (inner, inner2) for inner in outer(): print(inner()) # -> 2 3 5 4

funciona en python3.1-3.3