是否在类方法或其他地方使用代码cls().__ init __()?

时间:2017-07-27 00:00:37

标签: python

我在类方法中看到cls().__init__(),但似乎代码可能使用了简单的cls()。如:

class SomeCrazyClass:

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

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

这只是一个糟糕的编码风格选择,还是在某些情况下是cls().__init__()的实际用途?

1 个答案:

答案 0 :(得分:1)

cls().__init__()cls()之间的区别在于前者在实例上调用__init__两次,因此将返回None,后者将返回实际实例。

但是,再次调用__init__的假想场景可用于类的延迟初始化,也可能是其他一些用例。

例如,在下面的代码中,实例变量仅在第一次访问属性时加载:

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)

<强>演示:

>>> 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)

我们现在也可以从__init__返回一个通常不可能的值。