目录的python装饰器

目录的python装饰器,python,scripting,decorator,Python,Scripting,Decorator,我经常发现自己正在编写一个python脚本,其中包含参数: python my_script.py输入文件输出文件其他参数其他参数可选参数c 现在,我想要一个选项,要么像上面那样在单个文件上运行脚本,要么在目录中的每个文件上运行脚本。我发现自己正在编写一个新脚本my_script\u run\u on_directory.py,它查找目录中的每个文件,然后调用my_script.py,因此,我应该: python my\u script\u run\u on\u directory.py dir

我经常发现自己正在编写一个python脚本,其中包含参数:

python my_script.py输入文件输出文件其他参数其他参数可选参数c

现在,我想要一个选项,要么像上面那样在单个文件上运行脚本,要么在目录中的每个文件上运行脚本。我发现自己正在编写一个新脚本
my_script\u run\u on_directory.py
,它查找目录中的每个文件,然后调用
my_script.py
,因此,我应该:

python my\u script\u run\u on\u directory.py directory\u input directory\u output other\u parameter\u a other\u parameter\u b可选的\u parameter\u c

我需要经常这样做,并为每个
myu脚本
编写一个新的目录脚本。有更好的方法吗?我曾想过使用装饰器,但不确定最好的方法是什么

我想我想要的是

python general_run_on_directory_script.py my_script directory_input directory_output <and all other paremeters needed for my_script>
python general\u run\u on\u directory\u script.py my\u script directory\u input directory\u output

至于你关于使用什么的问题。一般来说,我会说将泛型代码抽象到一个函数中,该函数将特定函数作为参数。使用装饰器是一种相当干净的方法。所以在我看来,是的,这是一个很好的解决方案

简单情况(始终希望函数具有相同的参数):

更复杂的情况:

函数中的额外参数:

import os

def dir_or_file_decorator(func):
    def newFunc(path, *args, **kwargs):
        if os.path.isdir(path):
            filenames = os.listdir(path)
            for filename in filenames:
                filepath = os.path.join(path,filename)
                func(filepath, *args, **kwargs)
        else:
            func(path, *args, **kwargs)
    return newFunc

@dir_or_file_decorator       
def print_file_name_and_args(path, extra):
    print extra, path   

#We can use the parameter order in the function (our decorator assumes path is the first one)
print_file_name_and_args(r'c:\testdir', 'extra for test 1')
#Or we can just be safe and use named arguments (our decorator assumes the argument is named path)
print_file_name_and_args(extra='extra for test 1', path=r'c:\testdir')
#A combination of both is possible too (but I feel it's more complicated and hence more prone to error)
print_file_name_and_args(r'c:\testdir', extra='extra for test 1')

#Output (in all 3 cases):
# extra for test 1 c:\testdir\testfile1.txt
# extra for test 1 c:\testdir\testfile2.txt
还必须返回值:

import os

def dir_or_file_decorator_with_results(concatenateResultFunc):
    def dir_or_file_decorator(func):
        def newFunc(path, *args, **kwargs):
            if os.path.isdir(path):
                results = []
                filenames = os.listdir(path)
                for filename in filenames:
                    filepath = os.path.join(path,filename)
                    results.append(func(filepath, *args, **kwargs))
                return concatenateResultFunc(results)
            else:
                return func(path, *args, **kwargs)
        return newFunc
    return dir_or_file_decorator

#Our function to concatenate the results in case of a directory
def concatenate_results(results):
    return ','.join(results)

#We pass the function used to concatenate the results in case of a directory when we apply to decorator
#What happens is that we create a new dir_or_file_decorator that uses the specified concatenateResultFunc
#That newly created decorator is then applied to our function
@dir_or_file_decorator_with_results(concatenate_results)
def get_file_name_and_args(extra, path):
    return extra + ' -> ' + path    

#Test again
print get_file_name_and_args(r'c:\testdir', 'extra for test 1')

#Output:
# c:\testdir\testfile1.txt -> extra for test 1,c:\testdir\testfile2.txt -> extra for test 1

嗨,谢谢你的回复。所以你认为装饰师是正确的选择?包装器从何处获取您拥有的path变量?抱歉,发生了周末事件。我会用一个更深入的例子来更新我的答案。简而言之,包装器不需要获取路径变量,它返回一个接受路径变量的函数。在更新的示例中,这一点将更加清楚。
import os

def dir_or_file_decorator_with_results(concatenateResultFunc):
    def dir_or_file_decorator(func):
        def newFunc(path, *args, **kwargs):
            if os.path.isdir(path):
                results = []
                filenames = os.listdir(path)
                for filename in filenames:
                    filepath = os.path.join(path,filename)
                    results.append(func(filepath, *args, **kwargs))
                return concatenateResultFunc(results)
            else:
                return func(path, *args, **kwargs)
        return newFunc
    return dir_or_file_decorator

#Our function to concatenate the results in case of a directory
def concatenate_results(results):
    return ','.join(results)

#We pass the function used to concatenate the results in case of a directory when we apply to decorator
#What happens is that we create a new dir_or_file_decorator that uses the specified concatenateResultFunc
#That newly created decorator is then applied to our function
@dir_or_file_decorator_with_results(concatenate_results)
def get_file_name_and_args(extra, path):
    return extra + ' -> ' + path    

#Test again
print get_file_name_and_args(r'c:\testdir', 'extra for test 1')

#Output:
# c:\testdir\testfile1.txt -> extra for test 1,c:\testdir\testfile2.txt -> extra for test 1