2015-08-07 6 views
0

Что (если что-либо) на самом деле отличается между использованием имени во вложенной функции и передачей имени вложенной функции? Если нет различия, что предпочтительнее по соглашению?Передать имя вложенной функции в Python?

def foo(bar): 
    def put(): 
     bar.append('World!') 
     print(', '.join(bar)) 
    put() 
foo(['Hello']) 

против

def foo(bar): 
    def put(bar): 
     bar += ['World!'] 
     print(', '.join(bar)) 
    put(bar) 
foo(['Hello']) 
+1

related: http://stackoverflow.com/questions/1261875/python-nonlocal-statement – NightShadeQueen

+1

Как диктует Дзен Питона: «Явный лучше, чем неявный». В этом случае явное прохождение аргумента яснее, чем догадываться, откуда неожиданно появился «бар». – Wolph

+0

Вы говорите только о вложенных функциях, а не о закрытии? Значит, вы не собираетесь возвращать 'put' в качестве возвращаемого значения' foo'? – Cyphase

ответ

1

Разница заключается в том, что в первом, переменный бар находится в рамках родительской функции, он может быть использован в функции ребенка, если вы не сделаете задание на нем (Это было бы аналогично использованию global переменных в функции). Пример -

>>> def foo(bar): 
...  def put(): 
...   bar = bar + ['World'] 
...   print(', '.join(bar)) 
...  put() 
... 
>>> 
>>> foo(['Hello']) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 5, in foo 
    File "<stdin>", line 3, in put 
UnboundLocalError: local variable 'bar' referenced before assignment 

В этом случае, если вы хотите использовать bar и назначить на него, а также, что вам нужно использовать nonlocal ключевое слово, пример -

>>> def foo(bar): 
...  def put(): 
...   nonlocal bar 
...   bar = bar + ['World!'] 
...   print(', '.join(bar)) 
...  put() 
... 
>>> foo(['Hello']) 
Hello, World! 

В то время как во втором один, бар является локальной переменной для функции put() (потому что ее аргумент для нее) и может быть назначен без вышеуказанного UnboundLocalError, пример -

>>> def foo(bar): 
...  def put(bar): 
...   bar = bar + ['World!'] 
...   print(', '.join(bar)) 
...  put(bar) 
... 
>>> 
>>> foo(['Hello']) 
Hello, World! 

Я бы предпочел явно передать необходимые аргументы, как это было сделано во втором случае.

+0

Если вы не назначаете 'bar' во втором случае (либо с помощью' bar.append', либо '+ ='), то 'bar' не является локальным, не так ли? Его значение изменится в области foo после 'put (bar)'. Так что в моих отпечатках ... нет никакой разницы? – Ian

+0

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

1

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

def put(bar): 
    bar += ['World!'] 
    print(', '.join(bar)) 


def foo(bar): 
    put(bar) 


foo(['Hello']) 

Если для по какой-то причине вам нужно, чтобы он был вложен, лучше перейти в bar явно. Однако, если вы думаете, что вам нужно, чтобы он был вложен, сначала спросите о своих рассуждениях; есть хороший шанс, что вы этого не сделаете. :)

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