1

Currently, I have a @classmethod that returns the right class given a variable. It looks something like:

class Parent():
  @classmethod
  def GetInstance(cls, variable):
    if variable == 'foo':
      return Child()


class Child(Parent):
  def Something(self):
    pass

instance = Parent.GetInstance('foo')
result = instance.Something()

I prefer not to define and use GetInstance. Instead, I would like the Main() to simply be:

instance = Parent('foo')
result = instance.Something()

While keeping all the benefits of the structure above. I want class Parent() to return an object of class Child() when called, without the need of using a method. __init__ unfortunately does not seem to help, as it cannot return anything. Any ideas?

David C.
  • 1,974
  • 2
  • 19
  • 29
Edgar Derby
  • 2,543
  • 4
  • 29
  • 48
  • You can use `__new__`, but in many cases you're better off just writing a factory function. – BrenBarn Feb 10 '17 at 19:07
  • Yeah, Python's class model does not easily support this. I can't think of a way, because, as you have found out, `__init__` does not like to `return` things. Just use the factory pattern... this is well known. – juanpa.arrivillaga Feb 10 '17 at 19:07
  • @BrenBarn Yeah, I suppose you could use `__new__`. This would be a totally over-engineered solution to a non-problem. This would be totally surprising to anyone using your `class`. – juanpa.arrivillaga Feb 10 '17 at 19:09
  • I actually tried using __new__ and did not work. Maybe I did something wring, feel free to suggest actual implementation. – Edgar Derby Feb 10 '17 at 19:16
  • If using `__new__` didn't work, then you didn't do it correctly. You should share that code. – Kevin M Granger Feb 10 '17 at 19:19

3 Answers3

0

Just override 'new' special method. It's 'new' method which is responsible for calling creating an instance, allocating memory and then initialize it by calling 'init' . To be specific

new is static class method, while init is instance method. new has to create the instance first, so init can initialize it. Note that init takes self as parameter. Until you create instance there is no self.

hspandher
  • 15,934
  • 2
  • 32
  • 45
  • Looks to me that a problem is that you will get the call back: the `__new__` calls `Child()`, child calls the `Child`s `__new__` that will call the `Parent`s `__new__` and thus you will receive the call twice. – Willem Van Onsem Feb 10 '17 at 19:17
0

EDIT Ok, I went back and fixed it. Totally hackey and very brittle. I hope you don't want to keep extending this. I put this here as illustrative of why this is a bad idea.

Here is a sketch of how you could accomplish this. But please, just use a factory method.

>>> class Parent(object):
...     def __new__(typ, *args, **kwargs):
...         if args and args[0] == 'foo':
...             return Child()
...         else:
...             return super(Parent, typ).__new__(typ)
...
>>> class Child(Parent):
...     __new__ = object.__new__
...
>>> a = Parent('foo')
>>> a
<__main__.Child object at 0x1023275f8>
>>> p = Parent()
>>> p
<__main__.Parent object at 0x1023275c0>
>>>
juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
-1

Add a list of children[] in your parent class:

class Parent():
    def __init__(self):
        children = list()

That way you can create a child() object and then append it by doing:

child - Child()  # create new child obj
parent.children.append(child)

Then it should be simple to get a child from the list of children that you want using a loop etc.

  • The objective is not to create a list of children, but to pass a parameter and in case the parameter of `'foo'`, construct a child instead. – Willem Van Onsem Feb 10 '17 at 19:11
  • @WillemVanOnsem why don't you just post an answer? – codeglove26 Feb 10 '17 at 19:36
  • I did until I realized that the answer was not that trivial. Once you have admin rights, you can even see that answer ;). – Willem Van Onsem Feb 10 '17 at 19:37
  • @WillemVanOnsem yeah, I couldn't help but try. It's stupid and a good exercise to show why you should just use a factory method. It's almost as if this were some sort of *pattern* that *other software developers* had come up with to make their lives easier... – juanpa.arrivillaga Feb 10 '17 at 19:39