Any ideas about the best work around for __new__ losing its arguments?

后端 未结 3 994
没有蜡笔的小新
没有蜡笔的小新 2021-01-20 03:52

So, I only realised today that __new__ is deprecated for receiving arguments, as of python 2.6 (it isn\'t mentioned in the documentation, which is also not true

相关标签:
3条回答
  • 2021-01-20 04:33

    Well this made me curious because I did not see the deprecation in the documentation so I gave it a try myself.

    class Foo(object):
        def __new__(cls, a, b):
            if a:
                return a
            elif b:
                return b
            else:
                return super(Foo, cls).__new__(cls, a, b)
    
        def __init__(self, a, b):
            self.a = a
            self.b = b
    
    class Bar(Foo):
        def __new__(cls, x, y):
            if x:
                return x
            if y:
                return y
            else:
                return super(Bar, cls).__new__(cls, x, y)
    
    
    foo = Bar(False, False)
    

    As you can see in this example I overrode the init in Foo because any args passed to new will be forwarded to the cls instance that __new__ attempts to create. The instance of foo with be of a Bar class but it will have members a and b. I caused the super class's __init__ to be called by not overriding it. The method __new__ always passes its args on to __init__. If you don't override the __init__ for object it will fail since that method takes no args.

    That's my take on the usage of new in Python 2.7. According to the docs 2.6 is similar.

    0 讨论(0)
  • 2021-01-20 04:39

    __new__ is not "deprecated for receiving arguments". What changed in Python 2.6 is that object.__new__, the __new__ method of the object class, no longer ignores any arguments it's passed. (object.__init__ also doesn't ignore the arguments anymore, but that's just a warning in 2.6.) You can't use object as the terminating class for your inheritance if you want to pass arguments to __new__ or __init__.

    In order for any code to rely on that behaviour to work in 2.6, you just have to replace object as the baseclass, using a baseclass that properly accepts the extra arguments and does not pass them along in the calls it makes (using super().)

    0 讨论(0)
  • 2021-01-20 04:41

    Thomas put me right in his answer, but I should add that the solution in my case was trivial: add a __new__ method to my base class with the lines:

    class Base(object):
        def __new__(cls, *args, **kws):
            instance = super(Base, cls).__new__(cls)
            instance.__init__(*args, **kws)
            return instance
    
    0 讨论(0)
提交回复
热议问题