Python: всегда используйте __new__ вместо __init__?
Я понимаю, как работают __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 лучше в моей голове.
Ответы
Ответ 1
Один возможный ответ от guido post (спасибо @fraca7):
Например, в модуле рассола __new__
используется для создания экземпляров при несериализации объектов. В этом случае экземпляры создаются, но метод __init__
не вызывается.
Любые другие подобные ответы?
Я принимаю этот ответ как "да" на свой вопрос:
Мне интересно, может ли что-нибудь __init__
сделать, что __new__
не может?
Да, в отличие от __new__
, действия, которые вы помещаете в метод __init__
, не будут выполняться во время процесса рассыпания. __new__
не может сделать это различие.
Ответ 2
Итак, класс класса обычно 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__()
.
Ответ 3
Ну, ища __new__ vs __init__
на google показал мне этот.
Короче говоря, __new__
возвращает новый экземпляр объекта, а __init__
ничего не возвращает и просто инициализирует члены класса.
EDIT: Чтобы ответить на ваш вопрос, вам не нужно переопределять __new__
, если вы не подклассифицируете неизменяемые типы.