Почему __init __ () всегда вызывается после __new __ ()?

Усиление моего комментария к LukeH, полезному шаблону, если вам нужно будет использовать Reflection для вызова разных действий на основе параметра типа (в отличие от типа экземпляра объекта), чтобы создать частный общий статический класс, (этот точный код не проверен, но я уже делал это раньше):

static class FooInvoker<T>
{
  public Action<Foo> theAction = configureAction;
  void ActionForOneKindOfThing<TT>(TT param) where TT:thatKindOfThing,T
  {
    ...
  }
  void ActionForAnotherKindOfThing<TT>(TT param) where TT:thatOtherKindOfThing,T
  {
    ...
  }
  void configureAction(T param)
  {
    ... Determine which kind of thing T is, and set `theAction` to one of the
    ... above methods.  Then end with ...
    theAction(param);
  }
}

Обратите внимание, что Reflection генерирует исключение, если попытаться создать делегат для ActionForOneKindOfThing<TT>(TT param), когда TT не соответствует ограничениям этого метода. Поскольку система подтвердила тип TT, когда был создан делегат, можно безопасно вызывать theAction без дальнейшей проверки типов. Также обратите внимание, что если внешний код делает:

  FooInvoker<T>.theAction(param);

, для первого вызова потребуется любое отражение. Последующие вызовы просто вызовут делегата напрямую.

507
задан martineau 4 September 2017 в 16:22
поделиться

5 ответов

Использовать __new__ когда необходимо управлять созданием нового экземпляра.

Использовать __init__ когда необходимо управлять инициализацией нового экземпляра.

__new__ первый шаг создания экземпляра. Это звонило сначала и ответственно за возврат нового экземпляра Вашего класса.

Напротив, __init__ ничего не возвращает; это только ответственно за инициализацию экземпляра после того, как это было создано.

В целом Вы не должны должны быть переопределять __new__' если Вы не разделяете неизменный тип на подклассы как ул., интервал, unicode или кортеж.

С апреля 2008 сообщение: Когда использовать __new__ по сравнению с. __init__? на mail.python.org.

Необходимо полагать, что то, что Вы пытаетесь сделать, обычно делается с Фабрикой, и это - лучший способ сделать это. Используя __new__ не хорошее чистое решение, поэтому рассмотрите использование фабрики. Здесь у Вас есть хороший пример фабрики.

550
ответ дан 22 November 2019 в 22:29
поделиться

Однако я немного смущен относительно почему __init__ всегда называется после __new__.

Не большая часть причины, кроме которой это просто сделано тот путь. __new__ не несет ответственность инициализации класса, некоторый другой метод делает (__call__, возможно - я не знаю наверняка).

Я не ожидал это. Кто-либо может сказать мне, почему это происходит и как я реализую эту функциональность иначе? (кроме помещения реализации в __new__ который чувствует вполне hacky).

Вы могли иметь __init__ ничего не сделайте, если это было уже инициализировано, или Вы могли бы записать новый метакласс с новым __call__ тот единственные вызовы __init__ на новых экземплярах, и иначе просто возвращается __new__(...).

1
ответ дан 22 November 2019 в 22:29
поделиться

Заключить документацию в кавычки:

Типичные реализации создают новый экземпляр класса путем вызова суперкласса __ новый __ () метод, использующий "супер (currentclass, cls). __ новый __ (cls [...]) "с соответствующими аргументами и затем изменением недавно созданного экземпляра по мере необходимости прежде, чем возвратить его.

...

Если __ новый __ () не возвратит экземпляр cls, то новый экземпляр __ init __ () метод не будет вызван.

__ новый __ () предназначается главным образом, чтобы позволить подклассам неизменных типов (как интервал, ул. или кортеж) настраивать создание экземпляра.

23
ответ дан 22 November 2019 в 22:29
поделиться

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

Теперь, я собираюсь, что Вы пытаетесь реализовать шаблон "одиночка" в Python. Существует несколько способов сделать это.

Кроме того, с Python 2.6 можно использовать декораторов класса.

def singleton(cls):
    instances = {}
    def getinstance():
        if cls not in instances:
            instances[cls] = cls()
        return instances[cls]
    return getinstance

@singleton
class MyClass:
  ...
163
ответ дан 22 November 2019 в 22:29
поделиться

__ новый __ должен возвратить новый, пустой экземпляр класса. __ init __ затем назван для инициализации того экземпляра. Вы не звоните __ init __ в "НОВОМ" случае __ новый __, таким образом, это называют для Вас. Код, который звонит __new__ не отслеживает то, был ли __ init __ назван на конкретном экземпляре или не, ни если это, потому что Вы делаете что-то очень необычное здесь.

Вы могли добавить атрибут к объекту в __ init __ функция, чтобы указать, что это было инициализировано. Проверьте на существование того атрибута как первая вещь в __ init __ и не продолжайте двигаться дальше, если это было.

5
ответ дан 22 November 2019 в 22:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: