Function decorator that caches function results
Fredrik Lundh
fredrik at pythonware.com
Sun Oct 9 11:12:00 EDT 2005
Ron Adam wrote:
> In effect, 'cache' and 'fn' are replaced by the objects they reference
> before the cached_result function is returned.
not really; accesses to "free variables" always go via special cell objects
(rather than direct object references), and the compiler uses special byte
codes for all accesses to such objects.
this snippet illustrates the differences:
def func1():
return a
def func2(a):
return a
def wrapper(a):
def func3():
return a
return func3
def decode(func):
import dis
print func.__name__ + ":"
dis.dis(func)
print "co_freevars =", func.func_code.co_freevars
print "func_closure =", func.func_closure
print
decode(func1)
decode(func2)
decode(wrapper(10))
if you run this on a recent version of Python, you get something like:
func1:
2 0 LOAD_GLOBAL 0 (a)
3 RETURN_VALUE
co_freevars = ()
func_closure = None
func2:
5 0 LOAD_FAST 0 (a)
3 RETURN_VALUE
co_freevars = ()
func_closure = None
func3:
9 0 LOAD_DEREF 0 (a)
3 RETURN_VALUE
co_freevars = ('a',)
func_closure = (<cell at 0x0092C970: int object at 0x008A537C>,)
note the use of LOAD_DEREF for the variable access.
Other opcodes include STORE_DEREF (that updates a local variable
through a cell, used inside the "defining" scope), and MAKE_CLOSURE
(which sets up the function object for functions that actually uses
nested scopes; this is where the func_closure attribute is initialized).
(now, if I weren't limited to plain text, I could have drawn a nice little
diagram for you, but that's an entirely different thread...)
</F>
More information about the Python-list
mailing list