Когда (и почему) был представлен Python '__new __()'? - программирование

Когда (и почему) был представлен Python '__new __()'?

Когда (и почему) была введена функция Python __new__()?

Есть три шага в создании экземпляра класса, например, MyClass():

  • MyClass.__call__() вызывается. Этот метод должен быть определен в метаклассе MyClass.
  • MyClass.__new__() вызывается (__call__). Определено на самом MyClass. Это создает экземпляр.
  • MyClass.__init__() вызывается (также __call__). Это инициализирует экземпляр.

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

У нас есть старый код (все еще работающий!), Где __call__ перегружен. Причина была в том, что __new__ не было доступно в то время. Поэтому я попытался узнать больше об истории как Python, так и нашего кода, но я не мог понять, когда был введен __new__.

__new__ появляется в документации для Python 2.4, а не в документации для Python 2.3, но не появляется ни в одной из версий Python 2. Первый коммит, в котором было введено __new__ (слияние descr-branch обратно в trunk.), Который я смог найти, был сделан в 2001 году, но сообщение "back to trunk" указывает на то, что что-то было раньше. PEP 252 (создание типов, более похожих на классы) и PEP 253 (создание встроенных типов подтипов) нескольких месяцев назад представляются актуальными.

Если вы __new__ больше о введении __new__ вы __new__ больше о том, почему Python такой, какой он есть.


Изменить для уточнения:

Похоже, что class.__new__ дублирует функциональность, которая уже предоставлена metaclass.__call__. Кажется неуместным добавлять метод только для лучшей репликации существующих функций.

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

Должен быть one-- и, предпочтительно, только один --obvious способ сделать это.

4b9b3361

Ответ 1

Сообщение в блоге The Inside Story on New-Style Classes (из метко названного http://python-history.blogspot.com), написанное Guido van Rossum (Python BDFL), предоставляет некоторую хорошую информацию по этому вопросу.

Некоторые соответствующие цитаты:

В классах нового стиля появился новый метод класса __new__() который позволяет автору класса настраивать создание новых экземпляров класса. Переопределив __new__() автор класса может реализовать шаблоны, такие как шаблон Singleton, вернуть ранее созданный экземпляр (например, из свободного списка) или вернуть экземпляр другого класса (например, подкласс). Однако использование __new__ имеет и другие важные приложения. Например, в модуле pickle __new__ используется для создания экземпляров при десериализации объектов. В этом случае экземпляры создаются, но метод __init__ не вызывается.

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

Вы можете прочитать весь пост для получения дополнительной информации на эту тему.

Другой пост о New-style Classes который был написан вместе с цитируемым выше постом, содержит дополнительную информацию.

Редактировать:

В ответ на редактирование OP и цитату из Zen of Python я бы сказал это.
Zen of Python был написан не создателем языка, а Тимом Питерсом и был опубликован только 19 августа 2004 года. Мы должны учитывать тот факт, что __new__ появляется только в документации Python 2.4 (которая была выпущена в ноябре). 30, 2004), и этот конкретный принцип (или афоризм) даже не существовал публично, когда __new__ был введен в язык.

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

Ответ 2

Я не буду объяснять историю __new__ здесь, потому что я использовал Python только с 2005 года, поэтому после того, как он был введен в язык. Но вот обоснование этого.

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

В этом случае __new__ - это метод __new__, который создает и возвращает новый объект. Приятно отметить, что он все еще включен в определение класса и не требует определенного метакласса. Стандартная документация гласит:

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

Определение метода __call__ в метаклассе действительно разрешено, но IMHO не Pythonic, потому что __new__ должно быть достаточно. Кроме того, __init__, __new__ и метаклассы каждый копают глубже во внутреннем механизме Python. Так что правило должно быть не использовать __new__ если __init__ достаточно, и не использовать метаклассы, если __new__ достаточно.

Ответ 3

Метод __new__ позволяет создавать одноэлементные объекты, отслеживать созданные объекты и прочее. У вызываемых классов тоже много вариантов использования, наиболее распространенными из которых являются декораторы.