2016-07-14 9 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) 

は(transform_words()transform(word)によって渡さ時)機能surround_with()はそれのスコープ内の変数wordを手に入れた方法ですか?私は、周囲の値が何でなければならないのか(関数の引数として)保持変数だけを宣言したことを意味します。 wordはどのようにして入手できますか?

私はここで何が欠けていますか?私はそれを理解だと思う

+1

'transform_words 'の中で、関数' surround_with_value' **は** 'transform'です。実際には 'surround_with_value'が' surround_with_value(word) 'のスコープから外れてしまうので、実際には' surround_with_value(word) 'を呼び出すことになります。 '終わりですが、これはこれを考えるのが一番簡単な方法です)*。 – 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が返されます。

>>> 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 ' 

と閉鎖が逆参照され、その内容が使用されていることをあなたはそれを呼び出すたび:閉鎖として機能するオブジェクト参照surrounding。それは、変数transformに割り当てられ

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

そこでsurround_with()は、第3引数としてtransform_words()に渡され、(surround_with('*')の結果としての)関数オブジェクト、及びそのような関数を生成します

def transform_words(content, targets, transform): 

したがって、transformを呼び出すたびに、surround_with_value()関数は'*'というネストされた関数を実際にsurrounding閉鎖、及びwordが渡されている:

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

我々はsurround_with('*')を呼び出し、それは、値'{}{}{}'.format('*', word, '*')を返す機能surround_with_value()を返します。

今では非常に同じ関数が引数(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/

関連する問題