Почему randrange(start=100)` не вызывает ошибку?

В документации для randrange() говорится:

Аргументы ключевых слов не следует использовать, поскольку они могут быть интерпретированы неожиданным образом. Например, randrange(start=100) интерпретируется как randrange(0, 100, 1).

Если подпись random.randrange(start, stop[, step]), почему randrange(start=100) не вызывает ошибку, поскольку stop не передает значение?

Почему randrange(start=100) интерпретируется как randrange(0, 100, 1)?

Я не пытаюсь понять выбор дизайна того, кто написал код, а пытаюсь понять, как это вообще возможно. Я думал, что параметрам без значений по умолчанию необходимо передавать аргументы, иначе возникнет ошибка TypeError.

Моя версия Python показывает randrange(start, stop=None, step=1, _int=<class 'int'>) в реализации. Но обратите внимание, что при единственном аргументе start фактически становится stop.

Tom Karzes 30.06.2024 19:53

Одиночный параметр, передаваемый в range() или аналогичные функции, интерпретируется как значение остановки, а не как начало. Это обрабатывается специальным регистром внутри функции, это не то, что можно выразить в списке параметров функции.

jasonharper 30.06.2024 20:02

Но если предполагается, что единственный параметр должен быть stop=100, но имеет имя start=100, не должно ли это вызывать ошибку?

Joe 30.06.2024 20:04

вывод справки: randrange(start, stop=None, step=1) method of random.Random instance Choose a random item from range(stop) or range(start, stop[, step]).

folen gateis 30.06.2024 20:08

Первый параметр называется start, независимо от того, передаете ли вы его позиционно или через ключевое слово. Он просто интерпретируется как stop, если фактический параметр stop не указан.

jasonharper 30.06.2024 20:10

@jasonharper, понятно. Чтение исходного кода, указанного в опубликованном ответе, помогло мне это прояснить. Увидев random.randrange(start, stop[, step]) в документации, я подумал, что stop не имеет значения по умолчанию. Теперь я вижу, что это так. Наверное, я не понимаю, почему в документах не указана настоящая подпись.

Joe 30.06.2024 20:16

@Джо, если бы в документах это было указано как random.randrange(start[, stop, step]), то как бы ты узнал, какая подпись будет использоваться при вызове randrange(100)? В этом отношении документация верна, и то, что вы видите в коде, — это реализация, необходимая для поддержки двух подписей.

trincot 30.06.2024 20:19

@trincot, я думаю, это невозможно, потому что Python не разрешает параметры без значений по умолчанию после параметров со значениями по умолчанию. В противном случае я бы сказал, что подпись random.randrange(start=0, stop, step=1). Поэтому показаны две «подписи»?

Joe 30.06.2024 20:24

Учитывая, что есть две сигнатуры, я просто удивлен, что «специальный регистр» не использует один позиционный параметр в качестве stop, а выдает ошибку для (start=100). Является ли причина того, что при увеличении скорости не возникает ошибка?

Joe 30.06.2024 20:29

Что касается вашего предложения для random.randrange(start=0, stop, step=1): вы могли бы написать так, но эта подпись двусмысленна; например, когда вы вызываете randrange(2, 2): ​​это значения для начала/остановки или для остановки/шага?

trincot 30.06.2024 20:32

@trincot, да, я полагаю, это неоднозначно без четко определенного алгоритма анализа аргументов. Я предполагал, что для любого вызова потребуется передать как минимум столько же аргументов, сколько было параметров без значений по умолчанию, и что если их будет больше, они будут переданы в порядке, указанном в сигнатуре, так что, например, `def f(a=0, b, c=2, d, e=4, f):` при вызове с f(6,7,8,9) будет интерпретироваться как a=6, b=7, d=8, f=9. Но я знаю, что в Python это невозможно.

Joe 30.06.2024 21:42
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
11
58
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это связано с тем, что код randrange также должен поддерживать альтернативную подпись :

random.randrange(stop)

Реализация выполняет проверку, использует ли вызов эту подпись или другую:

random.randrange(start, stop[, step])

Это делается с помощью этого кода:

    istart = _index(start)
    if stop is None:
        if istart > 0:
            return self._randbelow(istart)

Это имеет смысл, когда вы вызываете randrange(100), где это переводится в вызов _randbelow(100), что и предполагалось.

Но когда вы вызываете randrange(start=100), мы попадаем в тот же поток, и значение start тоже интерпретируется как stop.

Другие вопросы по теме

Как сделать один из двух параметров обязательным, чтобы всегда присутствовал хотя бы один из двух?
Правильный стиль передачи сложных объектов в скрипт PowerShell
Как передать строковый параметр PowerShell, в котором есть `(обратный апостроф), ' и ' внутри?
Параметр с несколькими значениями возвращает одно значение Отчет Power BI с разбивкой на страницы
Я отправил запрос на публикацию, но продолжаю получать нулевое значение
Передача связанного списка в функцию LeetCode Add2number
Почему мы не можем иметь параметризованный конструктор родительского класса, если в дочерний класс не передается значение?
Создание функции, которая использует как ValueFromPipeline, так и ValueFromPipelineByPropertyName
Лучше ли передавать объект C++ по ссылке, чем по значению, если он находится в оперативной памяти?
Как заставить параметр переключателя работать с значением frompipelinebypropertyname?