0

Some code and descriptions:

# name_space.py

class Class1(object):
    var1 = 11
    def f1(self):
        print Class1.var1  # this will OK
        print var1  # this will be an error

def func_1():
    var1 = 11

    def func_2():
        print var1  # here will be OK

    func_2()

So, as we can see:

  1. Define a function in a class, the inner function doesn't have the ability to access the variables directly in the outer class. (We can still access the variables with the class name).
  2. Define a function in a function, the inner function has the ability to access the variables directly in the outer function.

More codes:

# name_space2.py

class A(object):
    def f1(self):
        def f2():            
            print f1  # this will be an error
            print A.f1  # this will OK
        f2()

So, why python use different scope mechanisms in function and class?

Exthen
  • 13
  • 3

3 Answers3

1

Because the lifetime and visibility of both is entirely different.

Class attributes are accessible by anything that can access the class. Class attributes also have to play with inheritance; what if I wrote code like this:

class Foo(object):
    def eggs(self):
        print eggs()

class Bar(Foo):
    def ham(self):
        print eggs()

By your logic, why should eggs be visible in Foo.eggs but not in Bar.ham?

Function locals are only accessible to the function and anything nested within the function. Call the function again and you get a fresh set of variables.

So when you create a class instance and call a method on that instance, the class attributes could have been changed by other code in the meantime. Function closures (locals accessed in a nested scope) cannot be changed from outside the function.

You cannot treat the two scopes as the same at all.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Great help, thanks very much! Learn a lot from "So when you create a class instance and call a method on that instance, the class attributes could have been changed by other code in the meantime." – Exthen Nov 29 '13 at 14:40
1

You are describing two mostly unrelated things, which happen to have similar indentation..

class Class1(object):
    var1 = 11

This is defining a new attribute on the Class1, you would access the var1 attribute either via Class1.var1, or inside one of the class's methods like self.var1, e.g:

class Class1(object):
    var1 = 11
    def f1(self):
        print self.var1

It's maybe more commonly seen in things like this:

class Class1(object):
    def mygetter(self):
        return 42
    def mysetter(self, val):
        print "mysetter got value of", val
    myprop = property(mygetter, mysetter)

..which you would use like this:

c = Class1()
print c.myprop # 42
c.myprop = 100 # prints "mysetter got value of 100"

Or often used for defining static attributes on classes, like this:

class Class1(object):
    THING = 1
    ANOTHER = "blah"
    ...

Remember these are defined at class definition time, so the attributes are shared between all instances of the class (something I found initially confusing)

The second thing you describe is lexical scoping, where variables are available in enclosed functions, often used like this:

def outer():
    myvar = 42
    def inner():
        print myvar * 2
    return inner
Community
  • 1
  • 1
dbr
  • 165,801
  • 69
  • 278
  • 343
  • The real difference is namespace and scope. Thanks very much! Gain a lot from you codes. And a little sorry, this site allows me to accept only one answer. – Exthen Nov 29 '13 at 14:54
0

There is no different mechanism.

var1 is not available inside method f1 because method's code is executed in the namespace where the method is called. var1 on the other hand exists in the class namespace.

Pawel Furmaniak
  • 4,648
  • 3
  • 29
  • 33