python __new__ - должен возвращать экземпляр cls

Согласно документации,

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

Если __new__ не возвращает экземпляр cls, метод __init__() нового экземпляра не будет вызван.

простейшая реализация __new__:

class MyClass:
    def __new__(cls):
        RetVal = super(currentclass, cls).__new__(cls)
        return RetVal

Как именно super(currentclass, cls).__new__(cls[, ...]) возвращает объект типа cls?

Этот оператор вызывает object.__new__(cls), где cls - MyClass.

Итак, как класс object узнает, как создать тип MyClass?


person Bob    schedule 29.07.2016    source источник
comment
Вы сказали ему, какой тип должен иметь возвращаемый объект. Для этого нужен параметр cls.   -  person user2357112 supports Monica    schedule 29.07.2016
comment
@ user2357112 Я не понимаю вашего ответа. Ожидаемый тип возврата - cls. Как super(currentclass, cls).__new__(cls) возвращает cls? Вы говорите, что он неявно его отбрасывает?   -  person Bob    schedule 29.07.2016
comment
object.__new__ смотрит на cls параметр, который вы ему передали, и говорит: "Ну и дела, я полагаю, Адриан хочет объект типа cls". Я должен сделать один из них.   -  person user2357112 supports Monica    schedule 29.07.2016
comment
@ user2357112 Хорошо. А как насчет заявления super(class1, class2); какая там логика? Он получает базовый класс, общий для обоих классов, что ли?   -  person Bob    schedule 29.07.2016
comment
Разве я не ответил вам на это несколько часов назад?   -  person user2357112 supports Monica    schedule 29.07.2016
comment
@ user2357112 Это правильно? Начнем с того, что super () сам по себе является просто сокращением для super (A, B), где A - это класс, в котором встречается код, и B - первый аргумент функции, в которой встречается код; так что в вашем конкретном случае Если это правильно, кажется бессмысленным; разве Python не знает, в какой функции находится код?   -  person Bob    schedule 29.07.2016
comment
Имеет ли значение, как Python это делает? object.__new__ возвращает новую структуру C, которая ссылается на объект класса. Все это делается на C. Это то, что вы ищете?   -  person Martijn Pieters    schedule 29.07.2016
comment
@MartijnPieters, object.__new__ ответ абсолютно логичен, и да, это то, что я ищу. Я также хотел бы знать синтаксис super. В документе в super(class1, class2) говорится, что issubclass(class2, class1) должно быть истинным. OK. Но как тогда super использовать ОБЕИХ классов, чтобы вернуть то, что он возвращает?   -  person Bob    schedule 29.07.2016
comment
@ Адриан: это совсем другой вопрос; Я написал несколько ответов о super(), которые охватывают это и многое другое.   -  person Martijn Pieters    schedule 29.07.2016
comment
@Adrian: имеет значение, в каком классе функция была изначально определена по отношению к MRO. «Волшебное» закрытие __class__ определяет это. Также см. Почему в Python 3.x есть волшебство super ()?   -  person Martijn Pieters    schedule 29.07.2016


Ответы (2)


super(MyClass, cls).__new__(cls) сначала ищет MRO (порядок разрешения методов) объекта cls (пропуская MyClass в этой последовательности), пока не найдет объект с атрибутом __new__.

В вашем случае это object.__new__:

>>> class MyClass:
...     def __new__(cls):
...         RetVal = super(MyClass, cls).__new__(cls)
...         return RetVal
...
>>> MyClass.__mro__
(<class '__main__.MyClass'>, <class 'object'>)
>>> hasattr(MyClass.__mro__[1], '__new__')
True

но если вы создали подкласс MyClass и смешали его с другим классом в MRO с помощью метода __new__, тогда это может быть другим методом.

object.__new__ реализован на C, см. object_new() функцию ; он содержит перехватчик для абстрактных базовых классов, чтобы убедиться, что вы не пытаетесь создать экземпляр абстрактного класса, а затем делегирует слот tp_alloc, который обычно устанавливается на _ 12_, который добавляет новую структуру PyObject в кучу. Именно эта структура представляет экземпляр интерпретатору.

person Martijn Pieters    schedule 29.07.2016
comment
Разве currentclass нельзя заменить на MyClass? - person Bob; 30.07.2016
comment
@ Адриан: Я следовал твоему примеру в твоем вопросе. Да, при правильном вызове будет использоваться MyClass. - person Martijn Pieters; 31.07.2016
comment
Ok. Итак, можете ли вы указать на документацию, в которой объясняется, что super(MyClass, cls) означает, то есть как super действует на свои два аргумента для возврата. . . что бы он ни вернулся. Python.org НЕ сообщает эту информацию. - person Bob; 31.07.2016
comment
@ Адриан: тогда я не знаю, на что тебе указать. Эта документация актуальна. - person Martijn Pieters; 31.07.2016
comment
Где в этой ссылке дан ответ на мой вопрос: как два аргумента супервыражения влияют / влияют на то, что возвращается? Он просто говорит, что второй аргумент должен быть подклассом первого аргумента. - person Bob; 31.07.2016
comment
@Adrian: super(type) возвращает несвязанный прокси, super(type, object-or-type) создает связанные атрибуты. Прокси-сервер использует атрибутный доступ для поиска в MRO таким же образом, как getattr(), пропуская type в этом порядке. - person Martijn Pieters; 31.07.2016
comment
@Adrian: документация предполагает, что вы знаете, что такое MRO и что делает привязка. Также см. Как я могу использовать super () с одним аргументом в python, где я углубляюсь в то, что означает привязка и как один аргумент из могут быть связаны постфактум. - person Martijn Pieters; 31.07.2016
comment
что означает привязка в этом случае? В моем примере: super (MyClass, cls) что связано с чем и что означает привязка? - person Bob; 31.07.2016
comment
ок, я прочитаю про mro и привязку. Спасибо, что нашли время - person Bob; 31.07.2016
comment
@Adrian: также см. протокол дескриптора; Связывание - это то, что происходит, когда вы ищите атрибуты экземпляра или класса, реализующего этот протокол. Это то, как методы получают аргумент self и как property объекты в конечном итоге вызывают функцию при доступе. - person Martijn Pieters; 31.07.2016

Несколько вещей, прежде всего вам нужно написать явное наследование от object вот так:

class MyClass(object):

Вам следует прочитать о старых классах и новые классы на python (только на python 2, в python 3 не имеет значения)

Что касается вашего вопроса, я думаю, вы упустили суть или синтаксис super() функций. Опять же, небольшое изменение в вашем коде:

RetVal = super(MyClass, cls).__new__(cls)

Таким образом, вы ссылаетесь на родительский класс, используя super(MyClass, cls) и вызывая метод из этого родительского класса новый (конечно, вы можете использовать любой другой метод)

edit Прочитав ваши комментарии, я просто добавлю, что super() не обязательно принимать какие-либо аргументы в Python 3, поэтому, возможно, для вас это более тривиально. Настоятельно рекомендуется узнать больше о super() здесь

person Or Duan    schedule 29.07.2016
comment
Я понимаю предполагаемый эффект. Я не понимаю, что делает передача cls в super в дополнение к MyClass. - person Bob; 29.07.2016
comment
Я знаю, что issubclass(class2, class1) должно быть правдой, но почему super нужно cls, чтобы возвращать то, что он возвращает? - person Bob; 29.07.2016
comment
Это вопрос о super(), а не о __new__(). - person Ignacio Vazquez-Abrams; 29.07.2016
comment
@Adrian Я добавил ссылки, чтобы вы могли узнать об этом больше, это другой вопрос, и на него следует ответить в другой теме. - person Or Duan; 29.07.2016