Почему или скорее, как объект .__ new__ работает по-разному в этих двух случаях

Версия Python: «2.7.3 (по умолчанию, 10 апреля 2013 г., 06:20:15) \ n [GCC 4.6.3]»

У меня есть это:

>>> class testclass1(object): ... pass ... >>> class testclass2(object): ... def __init__(self,param): ... pass ... >>> a = object.__new__(testclass1, 56) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: object.__new__() takes no parameters >>> b = object.__new__(testclass2, 56) >>> b <__main__.testclass2 object at 0x276a5d0> 

Еще веселее! Сравните с результатами testclass1 выше.

 >>> class testclass3(object): ... def __init__(self): ... pass ... >>> c = object.__new__(testclass3, 56) >>> c <__main__.testclass3 object at 0x276a790> >>> c1 = object.__new__(testclass3) >>> c1 <__main__.testclass3 object at 0x276a810> 

Мой вопрос: как (а не почему) object__new__ ведет себя по-разному в этих двух случаях? Также обратите внимание на ошибку, которая вводит в заблуждение в первом случае, потому что во втором случае object.__new__ конечном итоге принимает аргумент !.

3 Solutions collect form web for “Почему или скорее, как объект .__ new__ работает по-разному в этих двух случаях”

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

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

Рассмотрим варианты использования:

  1. Когда ни один из них не отменяется, мы хотим услышать жалобы на излишние (т. Е. Любые) аргументы, поскольку их присутствие может указывать на наличие ошибки.

  2. При определении неизменяемого типа мы скорее всего переопределим только __new__() , поскольку __init__() слишком поздно вызывается для инициализации объекта Immutable. Поскольку __new__() определяет подпись для типа, было бы больно переопределить __init__() чтобы остановить его от жалоб на избыточные аргументы.

  3. При определении типа Mutable мы можем переопределить только __init__() . Итак, здесь применимы обратные рассуждения: мы не хотим переопределять __new__() чтобы остановить его от жалоб.

  4. Когда __init__() переопределяется, а подкласс __init__() вызывает object.__init__() , последний должен жаловаться на избыточные аргументы; то же для __new__() .

Варианты использования 2 и 3 делают неприемлемым безошибочно проверять избыточные аргументы. Лучшим решением, которое учитывает все четыре варианта использования, является следующее: __init__() жалуется на избыточные аргументы, если только __new__() не переопределяется, а __init__() не переопределяется (IOW, если __init__() переопределен или __new__() не переопределяется) ; симметрично, __new__() жалуется на избыточные аргументы, если __init__() не переопределен, а __new__() не переопределен (IOW, если __new__() переопределен или __init__() не переопределяется).

Однако для обратной совместимости это слишком сильно перераспределяет код. Поэтому в 2.6 мы предупреждаем об избыточных аргументах, когда оба метода переопределены; для всех остальных случаев мы будем использовать приведенные выше правила.

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

Статический метод __new__ принимает в качестве первого аргумента класс. Другие аргументы будут переданы в метод __init__ этого класса. Поскольку ваш класс не имеет метода __init__ , __new__ не примет другие аргументы.

Взгляните на документацию для получения дополнительной информации.

Что касается «как», он реализован в C ( Objects/typeobject.c ), но вы можете выполнить эту же проверку с чистым Python:

 def __new__(cls, *args, **kwargs): ... if not hasattr(cls, '__init__') and (args or kwargs): raise TypeError("object.__init__() takes no parameters") ... 
  • Почему re.groups () не дает мне ничего?
  • Создать новый экземпляр класса из метода класса
  • Python: как сохранить список с объектами в файле?
  • Что это за "и" заявление, действительно делающее в обратном?
  • Путаница о том, как numpy применяется вдоль оси и понимает список
  • В Python, какой оператор переопределить для «if object:»?
  • Добавление атрибутов в объекты python
  • Как проверить методы, которые имеет объект, в Python?
  • Python - лучший язык программирования в мире.