Правильная подпись tuple.__new__
Функции и типы, реализованные на C, часто невозможно проверить, и их сигнатуры всегда выглядят так.
Правильная подпись tuple.__new__
:
__new__(cls[, sequence])
Например:
>>> tuple.__new__(tuple)
()
>>> tuple.__new__(tuple, [1, 2, 3])
(1, 2, 3)
Неудивительно, что это точно так же, как при вызове tuple()
, за исключением того факта, что вам нужно повторить tuple
дважды.
Первый аргумент __new__
Обратите внимание, что первым аргументом __new__
всегда является класс, а не экземпляр. Фактически, роль __new__
- создавать и возвращать новый экземпляр.
Специальный метод __new__
- это статический метод.
Я говорю это потому, что в вашем Row.__new__
я вижу self
: хотя имя аргумента не важно (кроме случаев использования аргументов ключевого слова), помните, что self
будет Row
или подклассом Row
, а не экземпляром. По общему соглашению первый аргумент следует называть cls
вместо self
.
Вернуться к вашим вопросам
Так как же self
передается __new__
в определении класса Row
?
Когда вы вызываете Row(...)
, Python автоматически вызывает Row.__new__(Row, ...)
.
Вы можете написать свой Row.__new__
следующим образом:
class Row(tuple):
def __new__(*args, **kwargs):
return tuple.__new__(*args, **kwargs)
Это работает, и в этом нет ничего плохого. Это очень полезно, если вас не волнуют аргументы.
- Есть ли у
__new__
какие-то тонкости, в которых его подпись может меняться в зависимости от контекста?
Нет, единственная особенность __new__
в том, что это статический метод.
- Или документация ошибочна?
Я бы сказал, что он неполный или неоднозначный.
- Почему метод
tuple.__new__
не имеет self
или cls
в качестве первого аргумента.
Он действительно есть, он просто не отображается на help(tuple.__new__)
, потому что часто эта информация не предоставляется функциями и методами, реализованными в C.
- Как я могу исследовать исходный код класса
tuple
, чтобы лично убедиться, что происходит на самом деле.
Ищете файл Objects/tupleobject.c
. В частности, вас интересует функция tuple_new()
:
static char *kwlist[] = {"sequence", 0};
/* ... */
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:tuple", kwlist, &arg))
Здесь "|O:tuple"
означает: функция называется "кортеж" и принимает один необязательный аргумент (|
ограничивает необязательные аргументы, O
обозначает объект Python). Необязательный аргумент может быть установлен через аргумент ключевого слова sequence
.
О help(type)
Для справки вы просматривали документацию type.__new__
, тогда как вам следовало остановиться на первых четырех строках help(type)
:
В случае __new__()
правильной подписью является подпись type()
:
class type(object)
| type(object_or_name, bases, dict)
| type(object) -> the object's type
| type(name, bases, dict) -> a new type
Но это не актуально, так как tuple.__new__
имеет другую подпись.
Помните super()
!
И последнее, но не менее важное: попробуйте использовать super()
вместо прямого вызова tuple.__new__()
.
person
Andrea Corbellini
schedule
25.12.2015
__new__
- это не экземпляр, а класс. Таким образом, его обычно называютcls
, а неself
. Под капотомtuple() == tuple.__new__(tuple)
иtuple(iterable) == tuple.__new__(tuple, iterable)
. - person GingerPlusPlus   schedule 25.12.2015object.__new__(cls[, ...])
вызывается для создания нового экземпляра классаcls
.__new__()
- это статический метод (в особом регистре, поэтому вам не нужно объявлять его как таковой) , который принимает класс, экземпляр которого был запрошен, в качестве своего первого аргумента. (выделено мной) - возвращаемое значение станетself
, переданным другим методам (в отличие, например, от__init__()
, который не имеет возвращаемого значения). - person martineau   schedule 25.12.2015cls
передается через*args
, посколькуobject.__new__
всегда должен передаватьсяcls
. Спасибо @martineau и @GingerPlusPlus. - person Paul   schedule 25.12.2015