ChrisFreeman
ChrisFreeman

Reputation: 6329

Is there a use for the code cls().__init__() in a classmethod or elsewhere?

I have seen cls().__init__() used in a classmethod, but it seems that the code could have used a simple cls() instead. As in:

class SomeCrazyClass:

    @classmethod
    def newclass(cls):
        return cls().__init__()

    @classmethod
    def newclass2(cls):
        return cls()

Is this just a poor coding style choice or is there a practical use of cls().__init__() in some situation?

Upvotes: 0

Views: 671

Answers (1)

Ashwini Chaudhary
Ashwini Chaudhary

Reputation: 250941

The difference between cls().__init__() and cls() is that former calls the __init__ on instance twice and hence will return None and the latter will return the actual instance.

But an imaginary scenario to of calling __init__ again can be used in lazy initialization of a class or may be some other use-cases as well.

For example in the below code the instance variables are loaded only on the first access of an attribute:

def init(cls, real_init):
    def wrapped(self, *args, **kwargs):
        cls.__init__ = real_init
    return wrapped


class A(object):
    def __new__(cls, *args, **kwargs):
        cls.__init__ = init(cls, cls.__init__)
        instance = object.__new__(cls)
        return instance

    def __getattr__(self, attr):
        expected_attrs = ('a', 'b')
        if attr in expected_attrs:
            self.__init__(range(10000), range(1000))
        return object.__getattribute__(self, attr)

    def __init__(self, a, b):
        print('inside __init__')
        self.a = sum(a)
        self.b = sum(b)

Demo:

>>> a = A()
>>> a.__dict__
{}
>>> a.a, a.b
inside __init__
(49995000, 499500)
>>> a.__dict__
{'a': 49995000, 'b': 499500}

>>> a = A()    
>>> a.__init__(range(10**5), range(10**4))
inside __init__    
>>> a.a, a.b
(4999950000, 49995000)

We can now also return a value from __init__ now which is usually not possible.

Upvotes: 1

Related Questions