[Python-ideas] For-loop variable scope: simultaneous possession and ingestion of cake

Dillon Collins dillonco at comcast.net
Tue Oct 14 06:03:03 CEST 2008


On Monday 13 October 2008, Arnaud Delobelle wrote:
> It's inefficient because it works by deconstructing and reconstructing
> the function bytecode.

That's not necessary.  Just make a new closure for it.  Here's some code (I 
was bored/curious).  The function reclose_kwds is provided for fun.   Enjoy:

def cell(v):
	"""Create a cell containing the arg via a dummy function"""
	def noop(): return v
	return noop.func_closure[0]

def reclose(func, closure):
	"""copy func, but use the given closure"""
	return function(func.func_code, func.func_globals,
		func.func_name, func.func_defaults, closure)

def reclose_kwds(func, **kwds):
	"""update func's closure using the names/values given as keywords"""
	cinfo = zip(func.func_code.co_freevars, func.func_closure)
	closure = tuple(cell(kwds[v]) if v in kwds else c for v,c in cinfo)
	return reclose(func, closure)

def close(*names):
	"""lock the given (non-global) variable names to their current values for
	function"""
	def _close(func):
		cinfo = zip(func.func_code.co_freevars, func.func_closure)
		closure = tuple(cell(c.cell_contents) if v in names else c for v,c in cinfo)
		return reclose(func, closure)
	return _close

def close_all(func):
	"""lock all non-global variables in function to their current values"""
	closure = tuple(cell(c.cell_contents) for c in func.func_closure)
	return reclose(func, closure)


def g():
	j=1
	def f():
		ret = []
		for i in range(3):
			#q=lambda x:x*i*j
			def q(x): return x*i*j
			ret.append(q)
		return ret
	return f()

def g2():
	j=1
	def f():
		ret = []
		for i in range(3):
			#q=close('i')(lambda x:x*i*j)
			@close('i')
			def q(x): return x*i*j
			ret.append(q)
		return ret
	return f()


q1, q2, q3 = g()
p1, p2, p3 = g2()

print q1, q1(2)
print q2, q2(2)
print q3, q3(2)
print
print p1, p1(2)
print p2, p2(2)
print p3, p3(2)
print



More information about the Python-ideas mailing list