views:

906

answers:

2

Im trying to understand scope in nested classes in python. Here is my example code :

class OuterClass:
     outer_var = 1
     class InnerClass:
           inner_var = outer_var

The creation of class does not complete and I get the error :

<type 'exceptions.NameError'>: name 'outer_var' is not defined

trying inner_var = Outerclass.outer_var doesnt work I get <type 'exceptions.NameError'>: name 'OuterClass' is not defined

I am trying to access the static outer_var from InnerClass

Is there a way to do this ? Thanks.

+5  A: 
class Outer(object):
  outer_var = 1

  class Inner(object):
    @property
    def inner_var(self):
      return Outer.outer_var

This isn't quite the same as similar things work in other languages, and uses global lookup instead of scoping the access to outer_var. (If you change what object the name Outer is bound to, then this code will use that object the next time it is executed.)

If you instead want all Inner objects to have a reference to an Outer because outer_var is really an instance attribute:

class Outer(object):
  def __init__(self):
    self.outer_var = 1

  def get_inner(self):
    return self.Inner(self)
    # "self.Inner" is because Inner is a class attribute of this class
    # "Outer.Inner" would also work, or move Inner to global scope
    # and then just use "Inner"

  class Inner(object):
    def __init__(self, outer):
      self.outer = outer

    @property
    def inner_var(self):
      return self.outer.outer_var

Note that nesting classes is somewhat uncommon in Python, and doesn't automatically imply any sort of special relationship between the classes. You're better off not nesting. (You can still set a class attribute on Outer to Inner, if you want.)

Roger Pate
It might be helpful to add with which version(s) of python your answer will work.
AJ
I wrote this with 2.6/2.x in mind, but, looking at it, I see nothing that wouldn't work the same in 3.x.
Roger Pate
+4  A: 

You might be better off if you just don't use nested classes. If you must nest, try this:

x = 1
class OuterClass:
    outer_var = x
    class InnerClass:
        inner_var = x

Or declare both classes before nesting them:

class OuterClass:
    outer_var = 1

class InnerClass:
    inner_var = OuterClass.outer_var

OuterClass.InnerClass = InnerClass

(After this you can del InnerClass if you need to.)

Jason Orendorff