In Python 3, if any value that is not an instance of cls
is returned, the __init__
method is never called. So 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 was under the impression that the order was __call__
(if it's an instance) -> __new__
-> __init__
.
However, in Python 2, this seems to raise a TypeError: this constructor takes no arguments
due to the lack of an __init__
. I can fix that by inheriting from object
. So, 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 around 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 reversed.
Is there any Python2/3 compatible way of doing this?
This is the way I did it. I don't like it, but it works:
class Foo(object):
@staticmethod
def __call__(i):
return i * 5
def __new__(cls, i):
return Foo.__call__(i)
Surely there is a more pythonic way of doing this.
In Python 2, you need to use new-style classes to make classes work properly. That means you need to define your class as class Foo(object)
. Then your first example will work in both Python 2 and Python 3.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With