这是我的Python 2.7脚本。
NoMethod
这是打印输出。
import os.path, shutil
def makeFolderName(num, dirBase='./interactive'):
destDir= dirBase + '-' + str(num) + '/'
if os.path.isdir(destDir):
num += 1
makeFolderName(num)
else:
shutil.copytree(dirBase, destDir)
print destDir
return destDir
folderName= makeFolderName(1)
print folderName
在该方法中,我认为如果./interactive-18/
./interactive-17/
./interactive-16/
./interactive-15/
./interactive-14/
./interactive-13/
./interactive-12/
./interactive-11/
./interactive-10/
./interactive-9/
./interactive-8/
./interactive-7/
./interactive-6/
./interactive-5/
./interactive-4/
./interactive-3/
./interactive-2/
./interactive-1/
====./interactive-1/
的值不是目录,则只会打印destDir
。它会将destDir
从最高值打印到最低值。
并且num
的值是最低folderName
,而不是最高值。
我希望num
返回一个目录名,其中makeFolderName
比当前目录中的名称高一个。
我做错了什么?
答案 0 :(得分:3)
您的错误是您应该在递归调用后返回:
if os.path.isdir(destDir):
num += 1
return makeFolderName(num)
else:
shutil.copytree(dirBase, destDir)
如果你不这样做,那么当makeFolderName
返回时,此功能将继续并运行以下代码,即num
的打印。但是,由于在从递归调用返回后完成,你会看到相反的数字。
答案 1 :(得分:2)
因为你需要在递归时返回,这会停止执行当前调用的其余部分:
if os.path.isdir(destDir):
num += 1
return makeFolderName(num)
其他一些事情值得一提:
(1)重新分配参数通常是值得避免的,这里不是必需的。而不是:
if os.path.isdir(destDir):
num += 1
return makeFolderName(num)
你可以写得更简单:
if os.path.isdir(destDir):
return makeFolderName(num + 1)
(2)如果你到达default Python maximum recursion depth,递归将失败,这可能会在几分钟内发生,几小时,几天和几天。或者周'时间取决于您的申请。如果您有1000多个./interactive-n
目录,那么您将获得例外。
这是一个迭代版本,如果有很多目录,它不会爆炸。它使用一些其他Python功能来简化和澄清代码。
注意使用下划线而不是camelCase的Python-like variable and function names越多。
(3)我将代码分开了:
查找新目录名
创建新目录
它让你做得更加明显。如果您从一开始就将问题分开,那么当您的函数库变得更大,并且您正在尝试追踪令人费解的行为时,您将会感谢自己。
import os
import shutil
def make_new_dir(num, original_dir='./interactive'):
new_dir = new_dirname(num, original_dir)
shutil.copytree(original_dir, new_dir)
return new_dir
def new_dirname(startnum, stem):
num = startnum
while True:
# Python 2.7-3.5
name = '{0}-{1}/'.format(stem, num)
# Python 3.6
# name = f'{stem}-{num}/'
if not os.path.isdir(name):
break
num += 1
return name
dirname = make_new_dir(1)
print(dirname)
(4)表现。每次调用原始方法时,它都会从num重新扫描现有的./interactive-n
目录。这是一个基于生成器的版本,可以记住它在哪里以及从该点开始搜索:
import os
import shutil
def make_new_dir(num, original_dir='./interactive'):
find_new_dir = unused_dirname(num, original_dir)
while True:
new_dir = next(find_new_dir)
shutil.copytree(original_dir, new_dir)
yield new_dir
def unused_dirname(startnum, stem):
num = startnum
while True:
# Python 2.7-3.5
name = '{0}-{1}/'.format(stem, num)
# Python 3.6
# name = f'{stem}-{num}/'
if not os.path.isdir(name):
yield name
num += 1
new_dir = make_new_dir(1)
print(next(new_dir))
print(next(new_dir))
print(next(new_dir))
>>> python makedir.py
./interactive-20/
./interactive-21/
./interactive-22/
(5)再次出于性能原因,您最终可能希望使用glob
检查现有目录(和文件):
>>> import glob
>>> glob.glob(r'./interactive-*')
['./interactive-1', './interactive-10', './interactive-11', './interactive-12', './interactive-13', './interactive-14', './interactive-15', './interactive-16', './interactive-17', './interactive-18', './interactive-19', './interactive-2', './interactive-20', './interactive-21', './interactive-22', './interactive-23', './interactive-24', './interactive-25', './interactive-3', './interactive-4', './interactive-5', './interactive-6', './interactive-7', './interactive-8', './interactive-9']
利用Python的一些优势,您可以为每个文件提取编号后缀:
>>> interactives = glob.glob(r'.\interactive-*')
>>> existing_dir_numbers = [int(interactive.split('-')[-1]) for interactive in interactives]
.split('-') splits a string into list elements at each dash. a_list[-1] returns the last element in a list. Since we know we're adding a
- N suffix to our directories, the last element is always a string version of
N , which we convert to a number using
int()函数`
>>> existing_dir_numbers
[1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 2, 20, 21, 22, 23, 24, 25, 3, 4, 5, 6, 7, 8, 9]
>>> max(existing_dir_numbers)
25
现在您可以选择./interactive-26
作为新目录名称。
答案 2 :(得分:1)
我认为这是您想要的更简单和迭代的代码:
def makeFolderName(num, dirBase='./interactive'):
destDir = dirBase + '-' + str(num) + '/'
while os.path.isdir(destDir):
num += 1
destDir = dirBase + '-' + str(num) + '/'
shutil.copytree(dirBase, destDir)
print destDir
return destDir
这里我们循环,直到找到一个不存在的interactive-num
,然后将文件复制到该目录并返回编号最大的目录名。
顺便提一下,根据this answer,默认情况下,一旦到达interactive-1000
,如果使用递归解决方案,Python会爆炸,因为Python对允许的递归深度有一个已定义的限制。
或者,如果您不喜欢重复destDir
作业:
def makeFolderName(num, dirBase='./interactive'):
destDir = ''
while True:
if not os.path.isdir(destDir):
break
num += 1
destDir = dirBase + '-' + str(num) + '/'
shutil.copytree(dirBase, destDir)
print destDir
return destDir
BTW,如果您有一个名为interactive-num
的文件而不是目录,除非您添加以下内容,否则它将被覆盖:
if not (os.path.isdir(destDir) or os.path.isfile(destDir[:-1]):
请勿忘记在检查文件时删除'/'
!