如何重构此代码不嵌套超过3“如果”

时间:2016-12-26 13:37:56

标签: python

python中的此函数将文件下载到AWS S3存储桶。我有一个代码问题,我不想嵌套三个“如果”,以便代码可以更清晰和可读:

            for fileinfo in response['Contents']:
                if key in fileinfo['Key']:
                    if '/' in fileinfo['Key']:
                        filekeysplit = fileinfo['Key'].rsplit('/', 1)
                        if filekeysplit[1] == '':
                            continue
                        if not os.path.exists(file):
                            os.makedirs(file)
                        fileout = os.path.join(file, filekeysplit[1])
                        self._s3.download_file(bucket, fileinfo['Key'], fileout)
                    else:
                        self._s3.download_file(bucket, fileinfo['Key'], file)

怎么做?谢谢

2 个答案:

答案 0 :(得分:1)

您始终可以反转测试并使用continue跳过迭代:

for fileinfo in response['Contents']:
    if key not in fileinfo['Key']:
        continue
    if '/' not in fileinfo['Key']:
        self._s3.download_file(bucket, fileinfo['Key'], file)
        continue

    filekeysplit = fileinfo['Key'].rsplit('/', 1)
    if filekeysplit[1] == '':
        continue
    if not os.path.exists(file):
        os.makedirs(file)
    fileout = os.path.join(file, filekeysplit[1])
    self._s3.download_file(bucket, fileinfo['Key'], fileout)

我们可以提出双download_file()次电话;跳过以/ 提前结尾的密钥。您只需要在循环外创建目录一次(我也在这里将file重命名为directory)。我在这里使用str.rpartition()而不是str.rsplit()

# file has been renamed to directory, no need to test,
# as `os.makedirs()` does this for us
os.makedirs(directory)

for fileinfo in response['Contents']:
    if key not in fileinfo['Key']:
        continue
    __, slash, basename = fileinfo['Key'].rpartition('/')
    if not basename and slash:  # ended in "/"
        continue

    target = directory
    if slash:  # there was a partition
        target = os.path.join(target, basename)
    self._s3.download_file(bucket, fileinfo['Key'], target)

答案 1 :(得分:1)

我想建议使用标准库的一些功能。就像Martijn Pieters所说的那样,你应该将你的file变量重命名为target_directory或类似的东西,因为如果你不这样做,它可能会使你的代码的读者感到困惑:

for fileinfo in response['Contents']:
    filepath_retrieved = fileinfo['Key']
    if key in filepath_retrieved:
        pathname_retrieved, filename_retrieved = os.path.split(filepath_retrieved)
        if pathname_retrieved:
            if filename_retrieved:
                os.makedirs(target_directory, exist_ok=True)
                output_filepath = os.path.join(target_directory, filename_retrieved)
                self._s3.download_file(bucket, filepath_retrieved, output_filepath)
        else:
            output_filepath = target_directory
            self._s3.download_file(bucket, filepath_retrieved, output_filepath)

使用的功能是:

  • os.path.split()而不是str.rsplit()或str.rpartition(),因为当您尝试执行fileinfo['Key'].rsplit('/', 1)
  • exist_ok os.makedirs()的参数,因此在您需要创建目录之前,不必担心目录的存在。