我编写代码以递归方式列出所有具有层次结构的目录和文件。在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
请告诉我代码背后的原因。
答案 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_dir
,os
被定义为本地变量。它仅存在于函数范围内。第二次递归调用recur_dir
时,未定义os
。因此,在第13行遇到os
时出现UnboundLocalError。
答案 1 :(得分:0)
因为import os
是在if
循环内定义的,所以当level
为0
即if 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 !