3

Here's my code which I use to create "cached" instances:

class Foo(object):
    _instances = {}

    def __new__(cls, index):
        if index in cls._instances:
            return cls._instances[index]
        instance = super().__new__(cls)
        cls._instances[index] = instance
        return instance

    def __init__(self, index):
        print('__init__: {0}'.format(index))

The problem appears when I already have an instance of the same index; it should do nothing except return the existing instance, but it also invokes __init__ on the new instance:

>>> f = Foo(1)
__init__: 1
>>> f.x = True
>>> b = Foo(1)
__init__: 1
>>> b.x
True

The problem is b = Foo(1) also prints __init__: 1 when it "shouldn't" (I don't want it to). Is there a way to prevent the__init__ from being called in such cases?

Skamah One
  • 2,456
  • 6
  • 21
  • 31
  • 1
    Why use `__init__` *at all*? You already have a `__new__` method.. just do the initialisation there. – Martijn Pieters Jul 03 '15 at 12:58
  • @MartijnPieters My professor said you should customize `__new__` when you're modifying how the instance is created, and use `__init__` for everything else, including initialization of its attributes... Would I be better off not using `__init__` here? **Edit:** Okay thanks... I'll just use `__new__` instead – Skamah One Jul 03 '15 at 12:59
  • 1
    `__init__`, if defined, is executed on *whatever `__new__` returns*. – jonrsharpe Jul 03 '15 at 13:00
  • 1
    @jonrsharpe but just to be precise, `__init__` is looked up on the value returned from `__new__`; it doesn't necessarily use `__init__` from the same class where `__new__` was defined. Of course, returning something from `__new__` that's of a different type from the current class is rather naughty. – Karl Knechtel Jul 03 '15 at 13:55
  • @KarlKnechtel good point well made – jonrsharpe Jul 03 '15 at 13:56

0 Answers0