Python---NameError:free variable 'attr_str' referenced before assignment in enclosing scope

5656 ワード

まず、動物書「流暢なPython」の126ページからのコードを見て、その例5-10のコードをファイルtagに書きます.py、このファイルはHTMLラベルを生成するために使用されます.
def tag(name,*content,cls = None,**attrs):
    """    html  ,in tag.py"""
    if cls is not None:
        attrs['class'] = cls
    if attrs:
        attr_str = ' '.join(' %s="%s"'%(attr,value) for attr,value in sorted(attrs.items()))
    else:
        attrs_str = ' '
    if content:
        return '
'
.join('%s%s>'%(name,attr_str,c,name) for c in content) else: return ''%(name,attr_str)

しかし、筆者はこのファイルを実現する際に、一つの問題が発生しました.
NameError: free variable 'attr_str' referenced before assignment in enclosing scope

エラーメッセージの大まかな意味は、自由変数‘attr_str’は、閉じた範囲内で値を付与する前に参照される.私が初めてこの問題に遭遇したとき、pythonは変数を宣言しなくてもいいのではないかと思いました.なぜこのような問題が発生するのでしょうか.このバグを解決する前に、自由変数とは何かを見てみましょう.自由変数:自己簡略書、『python学習ノート-local,global and free variable』を参照
When a name is used in a code block, it is resolved using the nearest enclosing scope. The set of all such scopes visible to a code block is called the block’s environment.
If a name is bound in a block, it is a local variable of that block. If a name is bound at the module level, it is a global variable. (The variables of the module code block are local and global.) If a variable is used in a code block but not defined there, it is a free variable.
以上の参照では、1つの変数が1つのコードブロックで使用されているが、このコードブロックで定義されていない場合、この変数が自由変数であることがわかります.上のコードからattr_strは使用されていますが、定義されていないのでpython shellはNameErrorエラーを投げ出しました.エラーの原因が見つかった以上、どうやって解決しますか?
  • ファイルの先頭にグローバル変数を定義する:
  • global attr_str      #      
    def tag(name,*content,cls = None,**attrs):
        """    html  ,in tag.py"""
        if cls is not None:
            attrs['class'] = cls
        if attrs:
            attr_str = ' '.join(' %s="%s"'%(attr,value) for attr,value in sorted(attrs.items()))
        else:
            attrs_str = ' '
        if content:
            return '
    '
    .join('%s%s>'%(name,attr_str,c,name) for c in content) else: return ''%(name,attr_str)
  • 関数内部での事前参照:
  • def tag(name,*content,cls = None,**attrs):
        """    html  ,in tag.py"""
        attr_str = ''
        if cls is not None:
            attrs['class'] = cls
        if attrs:
            attr_str = ' '.join(' %s="%s"'%(attr,value) for attr,value in sorted(attrs.items()))
        else:
            attrs_str = ' '
        if content:
            return '
    '
    .join('%s%s>'%(name,attr_str,c,name) for c in content) else: return ''%(name,attr_str)

    再びプログラムを実行するとokay!