[Python-Dev] classes and cell variables question
Jeremy Hylton
jeremy at alum.mit.edu
Fri Dec 29 20:29:58 CET 2006
On 12/19/06, tomer filiba <tomerfiliba at gmail.com> wrote:
> to my understanding of the object model, the code of snippet 1
> and snippet 2 should be equivalent. a class is just a "special function"
> that returns its locals automatically and passes them to the metaclass
> constructor:
>
> --- snippet 1 ---
> class foo(object):
> x = 5
> def f(self):
> print "f", x
>
> --- snippet 2 ---
> def bar():
> x = 5
> def g(self):
> print "g", x
> return locals()
> barcls = type("barcls", (object,), bar())
>
> but there's one big difference. classes don't create cell variables
> to hold bound external variables. the "bar" version works, because
> "x" is a bound cell variable, but the "foo" version fails, as it attempts
> to access "x" as a global.
Others have explained the rationale for this design choice, and the
PEP is a good source for what we were thinking at the time.
I thought it was worth adding that a) class variables can never be
access as free variables, as your example foo() shows, and b) you
could access a variable bound in a function scope in a method.
Example of b):
def spam():
x = 5 # provides the binding for the free variable x in methods of eggs
class eggs(object):
x = 6 # irrelevant for purposes of resolving the free variable in
the method spam
def spam(self): # can't have too much spam
return x
return eggs
spam()().spam() should return 5.
Jeremy
>
> .>>> barcls().g()
> g 5
>
> .>>> foo().f()
> f
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> File "<stdin>", line 4, in f
> NameError: global name 'x' is not defined
>
> for reference, i attached the code of all four functions below.
>
> my question is, how come classes don't create cell variables, like
> normal functions? was this done on purpose? does it have to
> do with inheritance? if so, what's wrong with my "bar" version?
>
>
> [1]
> # code of class foo
> ############################################################
> # 2 0 LOAD_NAME 0 (__name__)
> # 3 STORE_NAME 1 (__module__)
> # 3 6 LOAD_CONST 0 (5)
> # 9 STORE_NAME 2 (x)
> #
> # 4 12 LOAD_CONST 1 (<code object f at
> 009E5608, file "<stdin>", line 4>)
> # 15 MAKE_FUNCTION 0
> # 18 STORE_NAME 3 (f)
> # 21 LOAD_LOCALS
> # 22 RETURN_VALUE
>
> [2]
> # code of foo.f:
> ############################################################
> # 5 0 LOAD_CONST 1 ('f')
> # 3 PRINT_ITEM
> # 4 LOAD_GLOBAL 0 (x)
> # 7 PRINT_ITEM
> # 8 PRINT_NEWLINE
> # 9 LOAD_CONST 0 (None)
> # 12 RETURN_VALUE
>
> [3]
> # code of bar:
> ############################################################
> # 2 0 LOAD_CONST 1 (5)
> # 3 STORE_DEREF 0 (x)
> #
> # 3 6 LOAD_CLOSURE 0 (x)
> # 9 BUILD_TUPLE 1
> # 12 LOAD_CONST 2 (<code object g at
> 009F6698, file "<stdin>", line 3>)
> # 15 MAKE_CLOSURE 0
> # 18 STORE_FAST 0 (g)
> #
> # 5 21 LOAD_GLOBAL 0 (locals)
> # 24 CALL_FUNCTION 0
> # 27 RETURN_VALUE
>
> [4]
> # code of bar.g:
> ############################################################
> # 4 0 LOAD_CONST 1 ('g')
> # 3 PRINT_ITEM
> # 4 LOAD_DEREF 0 (x)
> # 7 PRINT_ITEM
> # 8 PRINT_NEWLINE
> # 9 LOAD_CONST 0 (None)
> # 12 RETURN_VALUE
> _______________________________________________
> Python-Dev mailing list
> Python-Dev at python.org
> http://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: http://mail.python.org/mailman/options/python-dev/jeremy%40alum.mit.edu
>
More information about the Python-Dev
mailing list