Mise en œuvre de la fermeture

Jetons un coup d'œil à l'implémentation des fermetures sur la base du contenu de l'article précédent (J'ai étudié à quoi ressemble la portée).

def counter(x):
	pprint(locals())
	def count():
		pprint(locals())
		y = x
		x += 1
		return y
	return count
c = counter(10)
print c()
print c()
print c() 

On dirait que cela fonctionne, mais quand je le fais, j'obtiens l'erreur suivante:

Résultat d'exécution


{'x': 10}
{}
Traceback (most recent call last):
  File "tes004.py", line 12, in <module>
    print c()
  File "tes004.py", line 7, in count
    y = x
UnboundLocalError: local variable 'x' referenced before assignment

L'argument x de la fonction counter () apparaît comme une variable locale de counter (). Si vous vous référez uniquement à la variable x de la fonction interne count (), la variable x peut être appelée variable locale de count (), mais le code d'affectation ( x + = 1 ⇒ C'est aussi le code de référence. ), Cela fonctionne donc comme une variable définie dans le bloc fonction count (), mais une erreur se produit car la référence est exécutée avant l'affectation. Vous pouvez faire référence aux variables définies par la fonction externe, mais vous ne pouvez pas les affecter (les réécrire).

Vient ensuite un modèle qui peut être bien exécuté.

def counter(x):
	pprint(locals())
	y = [x]
	def count():
		pprint(locals())
		z = y[0]
		y[0] += 1
		return z
	return count
c = counter(10)
print c()
print c()
print c() 

Résultat d'exécution


{'x': 10}
{'y': [10]}
10
{'y': [11]}
11
{'y': [12]}
12

Ce code semble également réécrire la variable y avec la fonction interne count (), mais cela fonctionne bien car il ne réécrit que le contenu de la liste qui peut être référencé par la variable y. Par exemple, changer y [0] + = 1 en `` y = [y [0] + 1] '' entraînera une erreur. C'est parce que nous essayons de réécrire la variable y. Par conséquent, même si la destination de référence n'est pas une liste mais une classe, la destination de référence peut être mise à jour.

Voici un exemple implémenté dans une classe.

class tcls():
	def __init__(self, x):
		self.x = x

def counter(x):
	pprint(locals())
	y = tcls(x)
	def count():
		pprint(locals())
		z = y.x
		y.x += 1
		return z
	return count
c = counter(10)
print c()
print c()
print c() 

Résultat d'exécution


{'x': 10}
{'y': <__main__.tcls instance at 0x0222F788>}
10
{'y': <__main__.tcls instance at 0x0222F788>}
11
{'y': <__main__.tcls instance at 0x0222F788>}
12

Recommended Posts

Mise en œuvre de la fermeture
fermeture
Exemple de fermeture Python
Python> fonction> Fermeture
Implémentation Keras de Shakedrop
Insérer l'implémentation du tri
Implémentation de la méthode de gradient 1
Image de fermeture