欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-04-12 11:56:59
...

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

再次运行程序就okay啦!

相关标签: python program