0
class SingletonLoader(object):
    cachedStates = {}

    def __new__(cls, key, loadFunc):
        print "SingletonLoader.new: cls = %s, key = %s, loadFunc = %s" % (cls, key, loadFunc)

        if key not in cls.cachedStates:
            plugin.msg("New key %s, invoking loader function %s" % (key, loadFunc))
            cls.cachedStates[key] = loadFunc()
            plugin.msg("Cached %s under key %s" % (key, cls.cachedStates[key]))

        return super(SingletonLoader, cls).__new__(cls, key, loadFunc)


    def __init__(self, key, loadFunc):
        # Set members from the cached state matching the key.
        self.__dict__ = self.__class__.cachedStates[key]

The line return super(SingletonLoad...... throws the error mentioned in the title.

Any idea why.

user1712258
  • 117
  • 3
  • 7

1 Answers1

1

super is not a drop-in replacement for the statically defined superclass of a class. There are two issues:

  1. If object.__new__ is indeed the next method in the MRO, then you can't pass additional arguments, as object.__new__ doesn't take them.

  2. If some other class C is next in the MRO, and C.__new__ does expect additional arguments, then you must supply them.

Bit of a catch-22, isn't it? The solution is that you must consider the class hierarchy as a whole when using super, especially so if you are using a method which might be executed by object. In this case, you must ensure that there is a base class that can both accept the additional arguments for __new__, and be guaranteed to have object be the next class in its MRO so that it can call __new__ without the extra arguments.

If you are simply using super to avoid writing object.__new__(cls), then you are using super incorrectly.

chepner
  • 497,756
  • 71
  • 530
  • 681
  • 1
    `object` is next in line, `SingletonLoader.mro() -> [__main__.SingletonLoader, object]`. Delegating to `type` which really knows how to make *new* stuff is usually what happens so I'm not sure what OP is trying to accomplish here. – Dimitris Fasarakis Hilliard Jan 20 '16 at 15:12
  • `object` is next in line in *this* case, which means the correct call is `super(SingletonLoader, cls).__new__(cls)`. But in general, `super` is intended for cooperative inheritance, which means you need to consider *any* class which might call the method. There's no guarantee that `super` will refer to `object`, since a descendent of of `SingletonLoader` might have a different MRO. – chepner Jan 20 '16 at 15:19
  • If you were trying to provide a general answer I concur and my bad; my comment was localized for the specific scenario that OP provided. – Dimitris Fasarakis Hilliard Jan 20 '16 at 15:22