Can a python class return a new instance of its class?

Question:

Is the following python code valid?

class Test:
  def __init__(self):
    self.number = 5

  def returnTest(self):
    return Test()
Asked By: cytinus

||

Answers:

Yes it is valid. The class is defined by the time you create an object and call the returnTest method.

In [2]: x = Test()

In [3]: y = x.returnTest()

In [4]: y
Out[4]: <__main__.Test instance at 0x1e36ef0>

In [5]: 

However, in cases where a method acts like a factory, you might want to consider using the classmethod decorator. When inheritance and other annoyances come in the way, this can help.

Answered By: Noufal Ibrahim

Yes, it’s valid. returnTest will not be run until it is called. It does not create an infinite loop, since the method is not called on the newly created object.

Answered By: mayhewr

Yes. It’s a valid python code. Many programming languages allow to return an instance of a class being defined. Think to the singleton pattern.

Answered By: user278064

Yes, it works but it appears that returnTest() is always the same instance of Test.

class Test:
  def __init__(self):
    self.number = 5

  def returnTest(self):
    return Test()


t = Test()
print t
print t.returnTest()
print t.returnTest()


$ python te.py
<__main__.Test instance at 0xb72bd28c>
<__main__.Test instance at 0xb72bd40c>
<__main__.Test instance at 0xb72bd40c>

This is true for Python 2.7 and 3.2. @classmethod didn’t make a difference. Interestingly enough, pypy returns a different instance each time:

$ pypy te.py
<__main__.Test instance at 0xb6dcc1dc>
<__main__.Test instance at 0xb6dcc1f0>
<__main__.Test instance at 0xb6dcc204>
Answered By: Mark Roberts

When working with subclasses, I suggest using something more like this:

return type(self)(*args, **kwargs)

This ensures that the returned type is the same as the class returning it.

Here’s a full example:

class Test():
    def __init__(self):
        self.number = 5

    def returnTest(self):
        return type(self)()

class SubTest(Test):
    def __init__(self):
        super().__init__()
        self.number = 6

t1 = Test()
t2 = SubTest()
print( type(t1.returnTest()), type(t2.returnTest()) )

Outputs:

<class '__main__.Test'> <class '__main__.SubTest'>
Answered By: ExperimentFailed
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.