[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