On 12/19/06, tomer filiba <[EMAIL PROTECTED]> 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@python.org > http://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: > http://mail.python.org/mailman/options/python-dev/jeremy%40alum.mit.edu > _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com