Any ideas on a better job around __new__ lose their argument?

So, I realized only today that __new__ deprecated for getting arguments, as from python 2.6 (it is not mentioned in the documentation, which is also incorrect from the point of view of the __new__ behavior of the __init__ call as far as I can see). This means that my functional code began to raise warnings, and I want to get rid of them. But I do not see an elegant way to get around.

I have a bunch of classes that perform optimization when they are built. So i

 class Conjunction(Base): def __new__(cls, a, b): if a == True: return b elif b == True return a else: return super(Conjunction,cls).__new__(cls, a, b) 

And so on (real versions cover many more cases). Unlike what Guido says in this answer (the only link to it I can find), my __new__ method uses its arguments and cannot replace with an overridden __init__ function.

The best I can do is split this into two parts:

 def Conjunction(a, b): if a == True: return b elif b == True return a else: return ConjunctionImpl(a, b) class ConjunctionImpl(Base): # ... 

But it's just ugly and stinks to heaven. Am I missing an elegant way for the class constructor to return any arbitrary object based on the constructor parameters that it specified?

+3
source share
3 answers

__new__ not "outdated to receive arguments". What has changed in Python 2.6 is that object.__new__ , the __new__ method of the __new__ class, no longer ignores the arguments passed to it. ( object.__init__ also no longer ignores arguments, but this is just a warning in version 2.6.) You cannot use object as the final class for your inheritance if you want to pass arguments to __new__ or __init__ .

So that any code can rely on this behavior to work in version 2.6, you just need to replace object as a base class, using a base class that properly takes extra arguments and doesn't pass them in its calls that it makes (using super() .)

+10
source

Thomas put me directly in response, but I have to add that the solution in my case was trivial: add the __new__ method to the base class with strings:

 class Base(object): def __new__(cls, *args, **kws): instance = super(Base, cls).__new__(cls) instance.__init__(*args, **kws) return instance 
+5
source

Well, that made me curious because I didn't see the fatigue in the documentation, so I tried it 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 tried init in Foo, because any arguments passed to the new one will be redirected to the cls instance that __new__ trying to create. An instance of foo with class Bar, but it will have elements a and b. I called the __init__ superclass to invoke without overriding it. The __new__ method always passes its arguments to __init__ . If you do not override the __init__ object for the object, it will not work, since this method takes no arguments.

What I take to use the new in Python 2.7. According to docs 2.6 similarly.

0
source

Source: https://habr.com/ru/post/1440498/


All Articles