2012-01-13 3 views
3

Можно создать дубликат:
“Least Astonishment” in Python: The Mutable Default Argumentфункции Python и пустые строки

Edit: Это не имеет ничего общего с recusion и просто изменяемые аргумент по умолчанию функция: "Least Astonishment" and the Mutable Default Argument

Многие спасибо

Я использую python 2.7.2 на win7 64bit машина и есть рекурсивная функция, которая действует на элемент LXML, функция выглядит следующим образом:

def recursive_search(start, stack = []): 
    for element in start.getchildren(): 
     if condition1(element): 
      stack = recursive_search(element, stack) 
     elif condition2(element) 
      stack.append(element) 
     else: 
      pass 
    return stack 

Когда я вызываю функцию впервые с:

output = recursive_search(starting_element) 

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

output += recursive_search(starting_element) 

или если стек был глобальной переменной. Если я называю это в третий раз я получаю 3 раза выход и т.д. и т.п.

Если я позвоню:

output = recursive_search(starting_element, []) 

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

Аналогично, если я изменить функцию таким образом, что он читает:

def recursive_search(start, stack = []): 
    if stack == []: 
     stack = [] 
    for element in start.getchildren(): 
     if condition1(element): 
      stack = recursive_search(element, stack) 
     elif condition2(element) 
      stack.append(element) 
     else: 
      pass 
    return stack 

, то я могу назвать:

output = recursive_search(starting_point) 

столько раз, сколько мне нравится, и снова не получить аномальное поведение.

Мой вопрос: что происходит - это ошибка или есть правило, о котором я не знаю, передавая пустые строки в рекурсивные функции в python?

+5

Ну, [изменяемый аргумент по умолчанию] (http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument) снова ... –

+0

Да, нечего делать с рекурсивными функциями. –

+0

aha, спасибо. –

ответ

4

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

В документации на Python имеется как минимум одна ссылка: http://docs.python.org/release/2.5.2/ref/function.html. См. Раздел «Значения параметров по умолчанию оцениваются при выполнении определения функции».

4

@ Марк уже объяснил это, так что вот решение.

def recursive_search(start, stack = None): 
    if stack is None: 
     stack = [] 
    for element in start.getchildren(): 
     if condition1(element): 
      stack = recursive_search(element, stack) 
     elif condition2(element) 
      stack.append(element) 
     else: 
      pass 
    return stack 

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


Некоторые варианты были бы,

stack = stack or [] 

# or 
if not stack: 
    stack = [] 

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

Когда вы сравните его с None, он будет заменен только в том случае, если stack содержит None. Я полагаю, что этот метод безопаснее.

+0

его не рекомендуется использовать 'if stack == None', используйте' if stack is None' вместо этого ([подробнее об этом] (http://jaredgrubb.blogspot.com/2009/04/python-is-none-vs -none.html)) – juliomalegria

+0

@julio, спасибо. Теперь это исправлено. Хорошая ссылка тоже. Никогда об этом не думал :) – FakeRainBrigand

Смежные вопросы