2

My question is probably easiest to see in code. I would like to do the following

class A():
    def __init__(self, i):
        self.i = i
        if i > 0:
            self.a = A(i-1)

The idea is that I want to create a class of type A that can recursively call its own constructor. If I code the above and attempt to create an instance of A I get the following:

a = Test(3)
--->  self.a = A(i-1)
NameError: global name 'A' is not defined

Is it possible to have a class that recursively calls its own constructor? If so, how is it done?

EliRibble
  • 41
  • 1
  • 5

2 Answers2

4

Seems to work fine for me when I do a = A(3), why is yours a = Test(3)? I'm guessing that is the issue, if you named your class Test then you should use self.a = Test(i-1).

>>> class A():
...     def __init__(self, i):
...         self.i = i
...         if i > 0:
...             self.a = A(i-1)
... 
>>> a = A(3)
>>> a.i
3
>>> a.a.i
2
>>> a.a.a.i
1
>>> a.a.a.a.a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: A instance has no attribute 'a'
Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
  • 1
    Aha! Turns out I get exactly the same output as you do when I use vanilla python. I was doing this using shell_plus in a django app using iPython. Turns out the error was related to my particular environment, not python itself. Thanks! – EliRibble Nov 09 '11 at 18:23
3

To recursively call the "constructor" (actually an initializer; see here) you do:

class A():
    def __init__(self, i):
        self.i = i
        if i > 0:
           self.__init__(i-1)

But I suspect that isn't what you're intending to do. Your example code is recursively creating instances of type A and storing them within each other.

Community
  • 1
  • 1
Nathan
  • 4,777
  • 1
  • 28
  • 35
  • 1
    +1 for the "initializer" mention. – jldupont Nov 08 '11 at 20:10
  • Yeah, my original post wasn't entirely clear. I do actually want to recursively create instances - I'm building something like a tree structure. – EliRibble Nov 10 '11 at 18:45
  • Have you tested this? I don't think this works. I tried this with assignment into a `dict`, and it returns `None` instead of a new object. Works just fine if I use the `ClassName(i-1)` syntax instead. – jonathan May 12 '18 at 10:03
  • @jonathan If you paste exactly the code that I provided, all it does is define a (old style) class with a silly initializer. If you add an instantiation "a = A(10)", then the code does run and a is set to a new instance of A with its "i" member equal to 0. – Nathan May 14 '18 at 19:19
  • @Nathan `self.__init__` cannot be an acceptable solution if it returns `None` when `A(i-1)` returns a value, and, as you're already noted, this solution doesn't *directly* answer the OP's question. My comment is specifically to counter the "+1 for the "initializer" mention", as it is misplaced in this context. – jonathan May 14 '18 at 20:57