鱼C论坛

 找回密码
 立即注册
查看: 1142|回复: 4

为何递归后必须返回上级目录

[复制链接]
发表于 2020-3-22 22:33:45 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
论坛上面有人问答这个问题,但是一直没看懂,求大神不吝赐教,
import os

def search_file(path,tp):
    os.chdir(path)
    file_all=os.listdir(os.curdir)

    for file_each in file_all:
        if os.path.isdir(file_each):
            search_file(file_each,tp)
##          os.chdir(os.pardir)
        if os.path.splitext(file_each)[1]=="."+tp:
            print(os.path.realpath(file_each))


path=input("请输入查找的初始目录:")
tp=input("请输入查找的文件类型【扩展名】:")
search_file(path,tp)

比如我要查找桌面上名称为1的文件家中包的文本文件(.txt)路径
文件夹1结构如下:
<1>
├123.txt
├<2>
│  └123.txt
├<3>
│  ├123.txt
│  ├<4>
│  │  └123.txt

注释掉 os.chdir(os.pardir)  后结果明显不正常。
结果如下:
请输入查找的初始目录:d:\desktop\1
请输入查找的文件类型【扩展名】:txt
d:\desktop\1\123.txt
d:\desktop\1\2\123.txt

从运行过程来看,递归进入子文件夹2后,返回,继续运行   for for file_each in file_all:  
file_each的值变为“3”,但接下来并未执行 if os.path.isdir(file_each) 或者认为判断为False,
所以就直接跳转至   if os.path.splitext(file_each)[1]=="."+tp:   然后就没有然后了。
感觉程序直接将文件夹3当成文件了,根本没有触及其内部文件及子文件夹。那么为什么
文件夹2可以递归而文件3就不行了呢?把文件夹3命名为文件夹0,文件夹0可以递归,文件夹2
又不行了。为什么呢?难道就是一条路走到黑,回来后就六亲不认了吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-3-22 23:26:33 | 显示全部楼层
本帖最后由 jackz007 于 2020-3-23 00:05 编辑

      因为在递归调用的时候,在函数入口,通过
def search_file(path,tp):
    os.chdir(path)
      无条件地把当前路径改变到次级子目录中了,而在函数退出的时候,却没有相应返回父目录的操作,因此,在递归调用前后,当前目录会发生改变。而这种改变会直接影响到后续子目录、文件的识别及子目录递归,导致函数无法正常运行。所以,在递归调用之后,必须通过下面的语句
            search_file(file_each,tp)
            os.chdir(os.pardir)
      把当前目录修改为父目录,其实,这是在恢复递归调用前的环境和状态,消除因函数递归调用而带来的有害改变,所以,这个操作是非常必要的!

      楼主可以试试修改的代码:
import os

def search_file(path , tp):
    cd = os . getcwd()
    os . chdir(path)
    try:
        for file_each in os . listdir() :
            if os . path . isdir(file_each) : 
                search_file(file_each , tp)
            elif os . path . isfile(file_each) :
                if os . path . splitext(file_each)[1] . lower() == tp . lower() :
                    print(os . path . realpath(file_each))
    except:
        pass
    os . chdir(cd)

path = input("请输入查找的初始目录:") . strip()
if path :
    if os . path . exists(path) and os . path . isdir(path) :
        tp = input("请输入查找的文件类型【扩展名】:") . strip()
        if tp :
            if tp[1] != '.' : tp = '.' + tp
        search_file(path , tp)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-23 10:27:35 | 显示全部楼层
jackz007 发表于 2020-3-22 23:26
因为在递归调用的时候,在函数入口,通过

      无条件地把当前路径改变到次级子目录中了,而在函 ...

当for语句循序至file_each=“3”(3是文件夹)时, 加上os.chdir(os.pardir)这行代码和注释掉这行代码,
vs code变量窗口看到的内容是完全相同的。
(return)abspath: 'd:\\desktop\\1\\123.txt'
file_all:['123.txt','2','3']
file_each:'3'
path:'d:\\desktop\\1'
(return) search_file:none
(return)splitext;('2','')
tp:'txt'

那么为什么接着运行,结果却不一样呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-23 10:55:13 | 显示全部楼层
yeahwsw 发表于 2020-3-23 10:27
当for语句循序至file_each=“3”(3是文件夹)时, 加上os.chdir(os.pardir)这行代码和注释掉这行代码,
...

        完全听不懂你在说什么,这么说吧,你是否接受递归后返回父目录的必要性?不要纠缠和讨论错误的代码,因为没有任何意义,除非,你确定自己每次都会在这里摔倒!!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-23 11:18:29 | 显示全部楼层
jackz007 发表于 2020-3-23 10:55
完全听不懂你在说什么,这么说吧,你是否接受递归后返回父目录的必要性?不要纠缠和讨论错误的代 ...

虽然没能解释我的问题,但是还是要谢谢你
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-25 07:49

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表