26

Imagine this:

class A(object):
 class B(object):
 def __init__(self):
 super(B, self).__init__()

This creates an error:

NameError: global name B is not defined.

I've tried A.B, but then it says that A is not defined.

Update:

I've found the problem.

I've had a class like this:

class A(object):
 class B(object):
 def __init__(self):
 super(B, self).__init__()
 someattribute = B()

In that scope, A isn't defined yet.

asked Dec 1, 2009 at 10:47
5
  • Using Python 2.6 both A.B, as well as self.__class__, seem to work. Commented Dec 1, 2009 at 11:07
  • A.B works fine for me. But are you sure you need multiple inheritance and super here? Don't jump to the MI world unless you really need it (you usually don't). If you do go that way you need to allow and pass-through *args and **kwargs in your __init__. Commented Dec 1, 2009 at 11:11
  • A is not defined in its own class block, so an A class variable _inner = B() will not work. Commented Dec 1, 2009 at 11:20
  • @Kaizer.se: Thanks, that was the problem. Commented Dec 1, 2009 at 11:34
  • A.B works for me - of cour I am not trying to instantiate B inside the A class block definition - that probably is what you are doing. The self.__class__ from Cory below should work then. Commented Dec 1, 2009 at 11:37

3 Answers 3

20

I'm not sure why A.B is not working correctly for you, as it should.. Here's some shell output that works:

>>> class A(object):
... class B(object):
... def __init__(self):
... super(A.B, self).__init__()
... def getB(self):
... return A.B()
... 
>>> A().getB()
<__main__.B object at 0x100496410>
answered Dec 1, 2009 at 11:04
Sign up to request clarification or add additional context in comments.

Comments

5

Since B will likely never be extended itself, this should work:

class A(object):
 class B(object):
 def __init__(self):
 super(self.__class__, self).__init__()
answered Dec 1, 2009 at 10:58

Comments

2

If the class A.B is unlikely to participate in any multiple inheritance, then you're better off just hard-coding the constructor call:

class A(object):
 class B(object):
 def __init__(self):
 object.__init__(self)

But if you really do need to have the full power of super, then you can get what you want by defining a custom descriptor that will initialize the B attribute lazily:

class LazyAttribute(object):
 def __init__(self, func, *args, **kwargs):
 self._func = func
 self._args = args
 self._kwargs = kwargs
 self._value = None
 def __get__(self, obj, type=None):
 if self._value is None:
 print 'created', self._value
 self._value = self._func(*self._args, **self._kwargs)
 return self._value
class A(object):
 class B(object):
 def __init__(self):
 super(A.B, self).__init__()
 someattribute = LazyAttribute(B)

This will cause the B attribute to be instantiated the first time it's accessed, and then reused thereafter:

>>> print A.someattribute
created <__main__.B object at 0x00AA8E70>
<__main__.B object at 0x00AA8E90>
>>> print A().someattribute
<__main__.B object at 0x00AA8E90>

For more info on descriptors, see: http://users.rcn.com/python/download/Descriptor.htm

answered Dec 1, 2009 at 19:10

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.