Difference between __new__ and __init__ order in Python2 / 3

In Python 3, if a value is returned that is not an instance cls, the method is __init__never called. Therefore, I can, for example, do this:

class Foo:
    @staticmethod
    def bar(n):
        return n * 5

    def __new__(cls, n):
        return Foo.bar(n)

print(Foo(3))  # => 15

I got the impression that the order was __call__(if it is an instance) → __new____init__.

However, in Python 2, this seems to boost TypeError: this constructor takes no argumentsdue to a lack __init__. I can fix this by inheriting from object. So by running this:

class Foo:
    def __new__(cls, *args, **kwargs):
        print("new called")

    def __init__(self, *args, **kwargs):
        print("init called")

Foo()
"""
Python2: "init called"
Python3: "new called"
"""

In Python 2, I even messed up with metaclasses.

Meta = type("Meta", (type,), dict(__call__=lambda self, x: x * 5))

class Foo(object):
    __metaclass__ = Meta

print(Foo(4))  # => 20

But this does not work in Python3 because the init / new methods seem to be canceled.

Is there a compatible Python2 / 3 way?

Decision:

So I did it. I don't like this, but it works:

class Foo(object):
    @staticmethod
    def __call__(i):
        return i * 5

    def __new__(cls, i):
        return Foo.__call__(i)

Of course, there is a more pythonic way to do this.

+4
1

Python 2 , . , class Foo(object). Python 2, Python 3.

+6

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


All Articles