2016-07-14 3 views
0

Итак, я читал этот wonderful piece, который пытается объяснить декораторы в python.Объем переменной при передаче другой функции в декораторах python

Мой вопрос относится только к этому фрагменту кода.

def surround_with(surrounding): 
    """Return a function that takes a single argument and.""" 
    def surround_with_value(word): 
     return '{}{}{}'.format(surrounding, word, surrounding) 
    return surround_with_value 

def transform_words(content, targets, transform): 
    """Return a string based on *content* but with each occurrence 
    of words in *targets* replaced with 
    the result of applying *transform* to it.""" 
    result = '' 
    for word in content.split(): 
     if word in targets: 
      result += ' {}'.format(transform(word)) 
     else: 
      result += ' {}'.format(word) 
    return result 

markdown_string = 'My name is Jeff Knupp and I like Python but I do not own a Python' 
markdown_string_italicized = transform_words(markdown_string, ['Python', 'Jeff'], 
     surround_with('*')) 
print(markdown_string_italicized) 

То, что я не понимаю, каким образом функция surround_with() получить переменную word (когда передается от transform(word) внутри transform_words()) в его область действия? Я имею в виду, что мы объявили только удерживающую переменную (как аргумент функции) для того, что должно быть для окружающей среды, и ничего больше. Тогда как это было word?

Что мне здесь не хватает?

+1

Обратите внимание, что внутри 'transform_words' функция' surround_with_value' ** является ** 'transform'. Поэтому, когда мы называем 'transform (word)', мы на самом деле вызываем 'surround_with_value (word)', потому что эти два имени относятся к одной и той же функции * (не совсем, на самом деле, поскольку 'surround_with_value' выходит за рамки, когда' surround_with 'заканчивается, но это самый простой способ подумать об этом) *. – jonrsharpe

+0

@jonrsharpe Это имеет смысл, я отправил ответ, основанный на моем понимании, вы можете проверить его правильность? –

ответ

1

surround_with() функция возвращает другой объект функции с закрытия:

def surround_with(surrounding): 
    """Return a function that takes a single argument and.""" 
    def surround_with_value(word): 
     return '{}{}{}'.format(surrounding, word, surrounding) 
    return surround_with_value 

Так surround_with_value возвращается; именно эта функция, которая присоединяет и добавляет значение surrounding к любой передается в:

>>> def surround_with(surrounding): 
...  """Return a function that takes a single argument and.""" 
...  def surround_with_value(word): 
...   return '{}{}{}'.format(surrounding, word, surrounding) 
...  return surround_with_value 
... 
>>> function = surround_with(' foo ') 
>>> function 
<function surround_with_value at 0x108ac16e0> 
>>> function('bar') 
' foo bar foo ' 

surround_with_value() функция была возвращена и ссылка на него хранилась во имя function. То, что ссылки на объект функции surrounding как закрытие:

>>> function.__closure__ 
(<cell at 0x108a8a590: str object at 0x1074c4060>,) 
>>> function.__closure__[0].cell_contents 
' foo ' 

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

Так surround_with() производит функциональный объект, и такую ​​функцию (как результат surround_with('*')), передается transform_words() как 3-й аргумент:

transform_words(markdown_string, ['Python', 'Jeff'], 
     surround_with('*')) 

так присвоенного переменной transform:

def transform_words(content, targets, transform): 

Таким образом, каждый раз, когда вы вызываете transform, вы действительно вызываете вложенную функцию surround_with_value() с '*' как surrounding закрытия, и word в настоящее время передается в:

result += ' {}'.format(transform(word)) 
0

Я думаю, что я понял,

Когда мы называем surround_with('*'), она возвращает функцию surround_with_value(), которая затем возвращая значение '{}{}{}'.format('*', word, '*').

Теперь эта же функция принимает аргумент (word), который затем передается внутри transform_words() и переименован в transform().

В нем мы, наконец, передаем значение для word.

+0

Это в значительной степени, да! – jonrsharpe

0

Закрытие может быть очень запутанным, и этот пример не может быть лучшим, чтобы показать почему surround_with_value() помнит объемный звук с (окружающим) случае, если это не в его объеме.

Я настоятельно рекомендую вам прочитать этот отличный блог, в котором представлена ​​вся концепция, которую вы должны понимать, чтобы понять декораторов. Шаг 1: Область действия -> Шаг 2: Закрытие -> Шаг 3: Декораторы

Потратьте некоторое время и прочитайте его с самого начала. http://simeonfranklin.com/blog/2012/jul/1/python-decorators-in-12-steps/

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