Реализация функции range в Python

Рейтинг: 2Ответов: 3Опубликовано: 18.01.2023

Всем известно про range() в python. Работал с аргументами и задался вопросом: Как в python удается так организовать передачу аргументов в функцию так, что если передать аргументы таким образом: (start, stop), где start и stop некоторые значения, что все передастся нормально, а если таким: (start) то функция range воспримет ее как stop. Можно ли реализовать подобный функционал в python и если да, то как?

Ответы

▲ 1

Это можно сделать с помощью аргументов по умолчанию (default arguments) в функции.

Например, функция range() определена следующим образом:

def range(start, stop=None, step=1):
    if stop is None:
        stop = start
        start = 0
    # код функции

Это означает, что если вы передаете только один аргумент в функцию range(), то он будет использован как stop, а start будет равен 0. Если вы передаете два аргумента, то они будут использованы как start и stop соответственно.

Вы можете реализовать подобный функционал в своей функции, используя аргументы по умолчанию и проверку на их значения внутри функции.

▲ 1

Примерно вот так:

def my_range(start, stop=None, step=None):
    if stop is None:
        stop = start
        start = 0
    if step is None:
        step = 1

    index = 0

    while True:
        tmp = start + index * step

        if step > 0 and tmp >= stop:
            break
        
        if step < 0 and tmp <= stop:
            break

        yield tmp
        index += 1


for i in my_range(5):
    print(i)

print('--------------------')

for i in my_range(2, 5):
    print(i)

print('--------------------')

for i in my_range(1, 5, 2):
    print(i)

print('--------------------')

for i in my_range(5, 0, -1):
    print(i)
▲ 1

CPython имеет открытый исходный код. Упрощённо реализация range выглядит так:

def validate_step(step):
    if step is None:
        return 1

    if step == 0:
        raise ValueError('range() arg 3 must not be zero')

    return step

def range(*args):
    start = stop = step = None

    match len(args):
        case 3:
            step = validate_step(args[2]);
            start = args[0]
            stop = args[1]
        case 2:
            start = args[0]
            stop = args[1]
            step = validate_step(step)
        case 1:
            stop = args[0]
            start = 0
            step = 1