相同的语句不同的位置导致不同的结果:在赋值之前引用的局部变量“os”

时间:2015-03-01 14:39:23

标签: python recursion

我编写代码以递归方式列出所有具有层次结构的目录和文件。在code1和code2之间只有一个区别,即“import os”的位置。
CODE1:

def recur_dir(dn,level=0,result=[]):
    import os
    new_queue=[]
    if level==0:
        dn=[dn]
    for item in dn:
        result.append([level,item])
        if  os.path.isdir(item):
            for next_item in os.listdir(item):
                next_dn = os.path.join(item, next_item)
                new_queue.append(next_dn)
    level=level+1
    if len(dn)>0: recur_dir(new_queue,level,result)
    return result


>>> z=recur_dir("/home/jack",0,[])  
>>> z    
[[0, '/home/jack'], [1, '/home/jack/.ssh'], [1, '/home/jack/.profile'], [1, '/home/jack/.bashrc'], [1, '/home/jack/wp.sh'], [1, '/home/jack/.bash_history'], [1, '/home/jack/.bash_logout'], [2, '/home/jack/.ssh/known_hosts']]

我想让'import os'在运行过程中只调用一次,将code1更改为code2。

CODE2:

 def recur_dir(dn,level=0,result=[]):
    new_queue=[]
    if level==0:
        dn=[dn]
        import os
    for item in dn:
        result.append([level,item])
        if  os.path.isdir(item):
            for next_item in os.listdir(item):
                next_dn = os.path.join(item, next_item)
                new_queue.append(next_dn)
    level=level+1
    if len(dn)>0: recur_dir(new_queue,level,result)
    return result  


>>> y=recur_dir("/home/jack",0,[])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 14, in recur_dir
File "<stdin>", line 9, in recur_dir
UnboundLocalError: local variable 'os' referenced before assignment

请告诉我代码背后的原因。

3 个答案:

答案 0 :(得分:2)

请注意,在回溯错误消息中:

Traceback (most recent call last):
  File "/home/unutbu/pybin/script.py", line 21, in <module>
    recur_dir('/tmp', 0, [])
  File "/home/unutbu/pybin/script.py", line 18, in recur_dir
    if len(dn)>0: recur_dir(new_queue,level,result)   <- RECUR_DIR IS CALLED
  File "/home/unutbu/pybin/script.py", line 13, in recur_dir
    if  os.path.isdir(item):
UnboundLocalError: local variable 'os' referenced before assignment

之后才会出现错误
if len(dn)>0: recur_dir(new_queue,level,result)
达到

。换句话说,UnboundLocalError正在筹集中 当recur_dir不再等于零时,第二次致电level

请注意,在import os内使用recur_diros被定义为本地变量。它仅存在于函数范围内。第二次递归调用recur_dir时,未定义os。因此,在第13行遇到os时出现UnboundLocalError。

答案 1 :(得分:0)

因为import os是在if循环内定义的,所以当level0if level==0:时,只导入os个模块。当使用level变量调用函数时,not equal to 0时间if条件为False,即import os语句未执行。

在第一个例子中:

import os在函数开始时定义,即每次调用when os模块时,我们都可以访问函数中的os。这就是为什么代码在第一个例子中工作的原因。


在py文件的开头定义模块的最佳方法。

OR

在函数中将模块定义在同一级别,其中函数可以在同一级别或嵌套级别访问模块。


e.g:

>>> def test(no):
...   if no==0:
...      import os
...   print "I am os:", os
... 
>>> test(0)
I am os: <module 'os' from '/usr/lib/python2.7/os.pyc'>
>>> test(10)
I am os:
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in test
UnboundLocalError: local variable 'os' referenced before assignment
>>> 

答案 2 :(得分:-1)

这个小实验将回答你的问题:

In [2]: def recur_dir(level=0):
         if level==0:
                 import os
         elif level == 2:
                 return
         print globals().keys(), locals().keys()
         recur_dir(level+1)
   ...:         


In [3]: recur_dir(0)
['_dh', '__', 'help', 'quit', '__builtins__', 'recur_dir', '_ih', '__builtin__', '__name__', '___', '__package__', '_', '_sh', '_i3', '_i2', '_i1', '__doc__', '_iii', 'exit', 'get_ipython', '_i', 'In', '_ii', '_oh', 'Out'] 
['os', 'level']
    ['_dh', '__', 'help', 'quit', '__builtins__', 'recur_dir', '_ih', '__builtin__', '__name__', '___', '__package__', '_', '_sh', '_i3', '_i2', '_i1', '__doc__', '_iii', 'exit', 'get_ipython', '_i', 'In', '_ii', '_oh', 'Out'] 
['level']

正如您所看到的,导入的 os 不会显示在全局范围内 - 它只会添加到本地范围。随着您对递归的深入研究,您将创建一个新的本地范围 - 它不包含 os