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

先看一段代码,这段代码来自动物书 《流畅的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 '\n'.join('<%s%s>%s'%(name,attr_str,c,name) for c in content)
    else:
        return '<%s%s/>'%(name,attr_str)

但是笔者在实现这个文件时,出现了一个问题:

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

错误信息的大概意思是:自由变量 ‘attr_str’ 在封闭范围内在赋值之前被引用
在我第一次遇到这个问题时,我想python不是不用声明变量吗?为什么还会出现这样的问题呢?在解决这个bug之前我们先来看看什么叫自由变量!
自由变量
参考自简书,《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.


以上的引用我们可以了解到自由变量的含义,如果一个变量在一个代码块中使用了,但是未在这个代码块中定义,那么这个变量就是自由变量。
从上面我们的代码我们可以看到, 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 '\n'.join('<%s%s>%s'%(name,attr_str,c,name) for c in content)
    else:
        return '<%s%s/>'%(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 '\n'.join('<%s%s>%s'%(name,attr_str,c,name) for c in content)
    else:
        return '<%s%s/>'%(name,attr_str)

再次运行程序就okay啦!

你可能感兴趣的:(Program,python)