ast wrote: > Hello > > Following syntax doesn't generate any errors: > > >>> foo=0 > >>> Class Foo: > foo > > But class Foo seems empty > > Is it equivalent to ? > > >>> class Foo: > pass
The resulting class is equivalent, but the expression `foo` is actually evaluated during class creation. You can easily see this when you replace foo with a print call, say: >>> for foo in "first", "second": ... class A: print(foo) ... first second If you compare the byte code you may note a small difference to def f(): foo >>> import dis >>> c = compile("class A: foo", "<nofile", "exec") >>> dis.dis(c) 1 0 LOAD_BUILD_CLASS 1 LOAD_CONST 0 (<code object A at 0x7f9cce602ae0, file "<nofile", line 1>) 4 LOAD_CONST 1 ('A') 7 MAKE_FUNCTION 0 10 LOAD_CONST 1 ('A') 13 CALL_FUNCTION 2 (2 positional, 0 keyword pair) 16 STORE_NAME 0 (A) 19 LOAD_CONST 2 (None) 22 RETURN_VALUE >>> c.co_consts[0] <code object A at 0x7f9cce602ae0, file "<nofile", line 1> >>> dis.dis(c.co_consts[0]) 1 0 LOAD_NAME 0 (__name__) 3 STORE_NAME 1 (__module__) 6 LOAD_CONST 0 ('A') 9 STORE_NAME 2 (__qualname__) The relevant instruction: 12 LOAD_NAME 3 (foo) 15 POP_TOP 16 LOAD_CONST 1 (None) 19 RETURN_VALUE For comparison a function: >>> def f(): foo ... >>> dis.dis(f) 1 0 LOAD_GLOBAL 0 (foo) 3 POP_TOP 4 LOAD_CONST 0 (None) 7 RETURN_VALUE In the class body LOAD_NAME is used instead of LOAD_GLOBAL. This allows dynamical scoping >>> foo = "outer" >>> class A: ... print(foo) ... foo = "inner" ... print(foo) ... outer inner >>> A.foo 'inner' whereas in the function you get an error: >>> def f(): ... print(foo) ... foo = "inner" ... print(foo) ... >>> f() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in f UnboundLocalError: local variable 'foo' referenced before assignment -- https://mail.python.org/mailman/listinfo/python-list