Python: всегда использовать __new__ вместо __init__? - PullRequest
27 голосов
/ 28 июня 2010

Я понимаю, как работают __init__ и __new__. Мне интересно, может ли __init__ что-то сделать, что __new__ не может?

т.е. можно использовать __init__ для замены следующим шаблоном:

class MySubclass(object):
    def __new__(cls, *args, **kwargs):
        self = super(MySubclass, cls).__new__(cls, *args, **kwargs)
        // Do __init__ stuff here
        return self

Я спрашиваю, поскольку хотел бы, чтобы этот аспект Python OO лучше подходил мне в голову.

Ответы [ 3 ]

22 голосов
/ 28 июня 2010

Итак, класс класса обычно равен type, и когда вы вызываете Class(), метод __call__() класса Class обрабатывает это.Я считаю, что type.__call__() реализован более или менее так:

def __call__(cls, *args, **kwargs):
    # should do the same thing as type.__call__
    obj = cls.__new__(cls, *args, **kwargs)
    if isinstance(obj, cls):
        obj.__init__(*args, **kwargs)
    return obj

Прямой ответ на ваш вопрос - нет, то, что __init__() может сделать (изменить / "инициализировать" указанный экземпляр),подмножество вещей, которые __new__() может сделать (создать или иным образом выбрать любой объект, который он хочет, сделать что-либо с этим объектом, который он хочет, прежде чем объект будет возвращен).тем не мение.Использовать __init__() проще (не нужно ничего создавать, ничего не возвращать), и я считаю, что лучше всегда использовать __init__(), если у вас нет особых причин использовать __new__().

4 голосов
/ 28 июня 2010

Один из возможных ответов из сообщения Гвидо (спасибо @ fraca7):

Например, в модуле pickle __new__ используется для создания экземпляров при десериализации объектов.В этом случае экземпляры создаются, но метод __init__ не вызывается.

Любые другие подобные ответы?


Я принимаю этот ответ как 'да, на мой собственный вопрос:

Мне интересно, может ли что-нибудь __init__ сделать то, что не может __new__?

Да, в отличие от __new__действия, которые вы указали в методе __init__, не будут выполняться во время процесса расслоения.__new__ не может сделать это различие.

2 голосов
/ 28 июня 2010

Ну, поиск __new__ vs __init__ в Google показал мне это .

Короче говоря, __new__ возвращает новый экземпляр объекта, в то время как __init__ ничего не возвращает и просто инициализируетученики.

РЕДАКТИРОВАТЬ: Чтобы действительно ответить на ваш вопрос, вам никогда не нужно переопределять __new__, если вы не подклассы неизменяемых типов.

...