2016-01-20 2 views
0

Я буду использовать функцию range в качестве основного примера в этом вопросе.Как методы Python обрабатывают произвольные параметры?

Я использую range для создания списка номеров. Тем не менее, я часто использую его с разными параметрами, в частности, с другим количеством NUMBER параметров. Меня удивляет, как range легко обрабатывает различное количество параметров и присваивает их их соответствующему значению (если они представляют наибольшее значение или наименьшее значение или интервал между значениями). Как это делает range? Использует ли он if инструкции для обработки каждого сценария или есть более эффективный способ?

+2

обрабатываются с использованием * args и ** kwargs, которые являются динамическими параметрами, которые не должны использоваться. но при использовании функция будет иметь интеллект для принятия этого параметра. см. http://stackoverflow.com/questions/3394835/args-and-kwargs и http: //www.saltycrane.com/blog/2008/01/how-to-use-args-and-kwargs-in-python/ –

ответ

1

Есть 2 способа обработки переменного числа аргументов, вы можете предоставить параметры по умолчанию:
Примечание: диапазон не реализует этот способ, но только здесь для иллюстрации:

def my_range(start=0, stop=None, step=1): 
    if stop == None: 
     start, stop = 0, start 
    while start < stop: 
     yield start 
     start += step 

Теперь вы можете позвонить это:

list(my_range(10))   # 0..9 
list(my_range(2, 10))  # 2..9 
list(my_range(10, step=2)) # 0,2,4,6,8 

другой способ заключается в использовании * для неназванной арг и ** для ключевого слова арга, выше реализованного с *args и **kwargs является много грязнее.

def my_range(*args, **kwargs): 
    d = {'start':0, 'stop':None, 'step':1} 
    for arg, v in zip(('start', 'stop', 'step'), args): 
     d[arg] = v 
    d.update(kwargs) 
    start, stop, step = (d[arg] for arg in ('start', 'stop', 'step')) 
    if stop == None: 
     start, stop = 0, start 
    while start < stop: 
     yield start 
     start += step 

Очевидно, что бывший гораздо легче реализовать, и последний, как правило, зарезервированы для особых случаев и не будет использоваться для реализации выше.

2

На более высоком уровне Python позволяет определить свои функции как:

def foo(*args, **kwargs) 

Эта форма абстрактного определения позволяет любое количество аргументов. Затем реализация является выбором разработчика. Прототипом функции диапазона является:

range(start, stop[, step]) 

Предполагается, что начинаются и останавливаются старт и остановка, а шаг необязателен. Однако реализация этого позволяет альтернативному прототипу

range(stop) 

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

0

функция Python allow a variable number of arguments, либо со значениями аргумента по умолчанию:

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

    while (step > 0 and start < stop) or (step < 0 and start > stop): 
     yield start 
     start += step 

(Это не полная реализация все семантики диапазона). В качестве альтернативы, используйте *args and **kwargs:

def range(*args, **kwargs): 
    if len(args) == 1: 
     start = 0 
     stop = args[0] 
     step = 1 
    elif len(args) == 2: 
     start, stop = args 
     step = 1 
    elif len(args) == 3: 
     start, stop, step = args 

    if 'start' in kwargs: 
     start = kwargs['start'] 
    if 'stop' in kwargs: 
     stop = kwargs['stop'] 
    if 'step' in kwargs: 
     step = kwargs['step'] 

    while (step > 0 and start < stop) or (step < 0 and start > stop): 
     yield start 
     start += step 

Обратите внимание, что стандартная библиотека range не принимает именованные аргументы, что значительно упрощает его реализацию.

+0

ваш первый пример НЕ эквивалентен диапазону в нескольких случаях, и условие останова не сможет выполнить другое, что 1 в обоих примерах – Copperfield

+0

@Copperfield Спасибо, исправлены оба. – phihag