Как встроенная функция диапазона принимает один аргумент или три?

Я хотел бы знать, может ли кто-нибудь сказать мне, как функция диапазона может принимать: единственный аргумент, range(stop) или range(start, stop) или range(start, stop, step) . Использует ли он variadic аргумент, такой как *arg для сбора аргументов, а затем использовать ряд операторов if для назначения правильных значений в зависимости от количества предоставленных аргументов? В сущности, range() указывает, что если есть один аргумент, то он устанавливается как аргумент stop, или если есть два, то они start и stop , или если их три, то они устанавливают их как stop , start , и step соответственно? Я хотел бы знать, как это можно было бы сделать, если бы кто-то написал диапазон в чистом Cpython. Благодаря!!!

Обновление : я не уточнил, когда я изначально задал вопрос, что я хотел узнать ответ на Cpython. Независимо благодарю вас за все ваши ответы! Я нашел их достаточно просвещенными. Это такая обратная связь, которая заставляет меня любить stackoverflow и людей, которые делают его настолько особенным!

Диапазон принимает, 1, 2 или 3 аргумента. Это может быть реализовано с def range(*args) и явным кодом для создания исключения, когда он получает 0 или более трех аргументов.

Он не может быть реализован с аргументами по умолчанию, потому что вы не можете иметь значение по умолчанию по умолчанию, например def range(start=0, stop, step=1) . Это связано с тем, что python должен выяснить, что означает каждый вызов, поэтому, если вам нужно было бы вызвать с двумя аргументами, python понадобилось бы какое-то правило, чтобы выяснить, какой аргумент по умолчанию вы переопределяете. Вместо того, чтобы иметь такое правило, это просто запрещено.

Если вы хотите использовать аргументы по умолчанию, вы можете сделать что-то вроде: def range(start=0, stop=object(), step=1) и иметь явную проверку типа stop .

Красота программного обеспечения с открытым исходным кодом заключается в том, что вы можете просто найти его в источнике :

(TL; DR: да, он использует varargs)

 if (PyTuple_Size(args) <= 1) { if (!PyArg_UnpackTuple(args, "range", 1, 1, &stop)) return NULL; stop = PyNumber_Index(stop); if (!stop) return NULL; start = PyLong_FromLong(0); if (!start) { Py_DECREF(stop); return NULL; } step = PyLong_FromLong(1); if (!step) { Py_DECREF(stop); Py_DECREF(start); return NULL; } } else { if (!PyArg_UnpackTuple(args, "range", 2, 3, &start, &stop, &step)) return NULL; /* Convert borrowed refs to owned refs */ start = PyNumber_Index(start); if (!start) return NULL; stop = PyNumber_Index(stop); if (!stop) { Py_DECREF(start); return NULL; } step = validate_step(step); /* Caution, this can clear exceptions */ if (!step) { Py_DECREF(start); Py_DECREF(stop); return NULL; } } 

Ответ lqc демонстрирует, как range реализован в C. Вам все же может быть интересно узнать, как range будет реализован, если встроенные функции Python были написаны на Python. Мы можем прочитать исходный код PyPy, чтобы узнать. Из pypy/module/__builtin__/functional.py :

 def range_int(space, w_x, w_y=NoneNotWrapped, w_step=1): """Return a list of integers in arithmetic position from start (defaults to zero) to stop - 1 by step (defaults to 1). Use a negative step to get a list in decending order.""" if w_y is None: w_start = space.wrap(0) w_stop = w_x else: w_start = w_x w_stop = w_y 

Первый аргумент, space , появляется как аргумент во всех встроенных функциях, которые я видел, поэтому я предполагаю, что это похоже на « self , когда пользователь напрямую не передает его. Из оставшихся трех аргументов два из них имеют значения по умолчанию; поэтому вы можете вызывать range с одним, двумя или тремя аргументами. Как интерпретируется каждый аргумент, зависит от количества аргументов.