1

I am reading a blog post on examples of overriding __new__ in python. However, I don't understand the following example:

class LimitedInstances(object):
    _instances = []  # Keep track of instance reference
    limit = 5 

def __new__(cls, *args, **kwargs):
    if not len(cls._instances) <= cls.limit:
        raise RuntimeError, "Count not create instance. Limit %s reached" % cls.limit    
    instance = object.__new__(cls, *args, **kwargs)
    cls._instances.append(instance)
    return instance

def __del__(self):
    # Remove instance from _instances 
    self._instance.remove(self)

Wouldn't calling object.__new__(cls, *args, **kwargs) cause infinite recursion? In addition, I saw that __new__ actually happens before an object exists. Then what is stored in cls exactly?

  • The blog post you linked provides an answer to your 2nd question: "Method __new__ will take class reference as the first argument" – nicoco Jan 30 '19 at 10:27
  • @nicoco ok...I think I mixed up object reference and class reference. Thanks a lot! –  Jan 30 '19 at 10:39
  • This code example is broken. `_instances` keeps a reference to each of its elements, and `__del__` is only called when an object has zero references. Thus, an object can never be removed from `_instances` as it being present in `_instances` guarentees it has a reference count of at least 1. – Dunes Jan 30 '19 at 10:54
  • In fact it's all sorts of broken. It limits creation to `limit+1` instances, probably not the expected behaviour. And it may call `object.__new__` with non-empty `args` or `kwargs` which is an error. It's also written in Python 2. I would suggest this blog is not a great resource for learning Python 3 or even Python 2. – Dunes Jan 30 '19 at 11:02

2 Answers2

1

Wouldn't calling object.__new__(cls, *args, **kwargs) cause infinite recursion?

Nope, why ? object.__new__ is not LimitedInstances.__new__ and will not call LimitedInstances.__new__ either.

nb : it would be better to use super() instead of hardcoding object, but that's unrelated.

in addition, I saw that new actually happens before an object exists.

Indeed - __new__ is the real constructor - it's responsability is precisely to create a new (uninitialized) instance of cls.

Then what is stored in cls exactly?

The class itself (in your case, LimitedInstances). How would you know (well, how would object.__new__ know) which class should be instanciated else ?-)

bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118
0

Calling object.__new__ in LimitedInstances.__new__ does not cause infinite recursion because they are different functions and object.__new__ does not call back to LimitedInstances.__new__. The call heiraracy looks something like:

LimitedInstances()
    LimitedInstances.__new__(LimitedInstances)
        object.__new__(LimitedInstances)
    object.__init__(instance) # (as there is not LimitedInstances.__init__)

It can get a bit more complicated than that, but in general this is what happens when you call a class.

Dunes
  • 37,291
  • 7
  • 81
  • 97