__new__ не вызывается при создании объекта

1

Случай 1:

class Person:
    def __new__(cls, *args, **kwargs):
        print "called"
        return super(Person, cls).__new__(cls, *args, **kwargs)

p=Person()

случай 2:

class Person(object):
    def __new__(cls, *args, **kwargs):
        print "called"
        return super(Person, cls).__new__(cls, *args, **kwargs)

p=Person()

В первом случае метод __new__() не вызывается, а во втором случае.

Если он не вызван, то как создается объект Person?

  • 0
    Я 99,999% уверен , что у вас есть это назад, и __new__ не называется в первом случае, но во втором.
  • 0
    Смотрите здесь для теста.
Показать ещё 1 комментарий
Теги:
class
object
oop
python-2.x

2 ответа

2

Я думаю, что это связано с новыми и старыми классами стилей в Python2:

В классах старого стиля фактически нет метода __new__, потому что для них __init__ является конструктором, поэтому в основном, если бы мы имели бы:

class A:

    def __new__(cls):
        print "A.__new__ is called"  # -> this is never called

A()

тело __new__ никогда не будет выполнено в этом случае, потому что это не цель для классов старого стиля.

В Python3 поведение одинаково, не имеет значения, явно ли вы наследуете object или нет:

class Person1:
    def __new__(cls, *args, **kwargs):
        print("called")
        return super(Person1, cls).__new__(cls, *args, **kwargs)


class Person2(object):
    def __new__(cls, *args, **kwargs):
        print("called")
        return super(Person2, cls).__new__(cls, *args, **kwargs)


p1 = Person1()
p2 = Person2()

Они должны печатать "вызываемый" дважды при вызове из 3.x.

  • 2
    Причина того, что поведение в Python 3 такое же, заключается в том, что вы всегда наследуете от object , говорите ли вы так или нет (что означает, что классы старого стиля отсутствуют).
  • 0
    В любом случае, обычно я бы рекомендовал ссылку на документ, но, AFAIK, единственная документация для этого находится под стандартными описаниями иерархии типов «Типы классов» и «Классические классы», и это далеко не ясно. Возможно, что-то есть в (несколько незаконченных / устаревших) документах по классам нового стиля .
Показать ещё 1 комментарий
1

Я искал документацию и, наконец, нашел ее здесь: https://staging2.python.org/dev/peps/pep-0253/

Объект типа имеет новый слот tp_new, который может выступать в качестве фабрики для экземпляров типа. Теперь типы вызываются, потому что слот tp_call установлен в PyType_Type (метатип); функция ищет слот tp_new вызываемого типа.

Чтобы добавить ответ @devforfu, в старые времена __new__ не существовало. Он был добавлен с добавлением классов нового стиля.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню