Усиление моего комментария к 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);
, для первого вызова потребуется любое отражение. Последующие вызовы просто вызовут делегата напрямую.
Использовать
__new__
когда необходимо управлять созданием нового экземпляра.Использовать
__init__
когда необходимо управлять инициализацией нового экземпляра.
__new__
первый шаг создания экземпляра. Это звонило сначала и ответственно за возврат нового экземпляра Вашего класса.Напротив,
__init__
ничего не возвращает; это только ответственно за инициализацию экземпляра после того, как это было создано.В целом Вы не должны должны быть переопределять
__new
__' если Вы не разделяете неизменный тип на подклассы как ул., интервал, unicode или кортеж.
С апреля 2008 сообщение: Когда использовать __new__
по сравнению с. __init__
? на mail.python.org.
Необходимо полагать, что то, что Вы пытаетесь сделать, обычно делается с Фабрикой, и это - лучший способ сделать это. Используя __new__
не хорошее чистое решение, поэтому рассмотрите использование фабрики. Здесь у Вас есть хороший пример фабрики.
Однако я немного смущен относительно почему
__init__
всегда называется после__new__
.
Не большая часть причины, кроме которой это просто сделано тот путь. __new__
не несет ответственность инициализации класса, некоторый другой метод делает (__call__
, возможно - я не знаю наверняка).
Я не ожидал это. Кто-либо может сказать мне, почему это происходит и как я реализую эту функциональность иначе? (кроме помещения реализации в
__new__
который чувствует вполне hacky).
Вы могли иметь __init__
ничего не сделайте, если это было уже инициализировано, или Вы могли бы записать новый метакласс с новым __call__
тот единственные вызовы __init__
на новых экземплярах, и иначе просто возвращается __new__(...)
.
Заключить документацию в кавычки:
Типичные реализации создают новый экземпляр класса путем вызова суперкласса __ новый __ () метод, использующий "супер (currentclass, cls). __ новый __ (cls [...]) "с соответствующими аргументами и затем изменением недавно созданного экземпляра по мере необходимости прежде, чем возвратить его.
...
Если __ новый __ () не возвратит экземпляр cls, то новый экземпляр __ init __ () метод не будет вызван.
__ новый __ () предназначается главным образом, чтобы позволить подклассам неизменных типов (как интервал, ул. или кортеж) настраивать создание экземпляра.
__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:
...
__ новый __ должен возвратить новый, пустой экземпляр класса. __ init __ затем назван для инициализации того экземпляра. Вы не звоните __ init __ в "НОВОМ" случае __ новый __, таким образом, это называют для Вас. Код, который звонит __new__
не отслеживает то, был ли __ init __ назван на конкретном экземпляре или не, ни если это, потому что Вы делаете что-то очень необычное здесь.
Вы могли добавить атрибут к объекту в __ init __ функция, чтобы указать, что это было инициализировано. Проверьте на существование того атрибута как первая вещь в __ init __ и не продолжайте двигаться дальше, если это было.