我想构建不同的函数,其中每个函数都必须使用一个文件。我用装饰器实现了这个。
请让我知道它是否可以更像 pythonic:
def open_file(func):
def a_wrapper(filename,separator,*args):
f = open(filename,'w')
return func(f,separator,*args)
return a_wrapper
@open_file
def write_multiple_items(file, sep, *args):
file.write(sep.join(args))
@open_file
def write_one_item(file,sep,name):
file.write(sep.join(name))
write_multiple_items('foo.txt','--',"Hello","World", "!!!!")
write_one_item('bar.txt','--',"Bye World !!!")
我应该关闭文件吗?怎么办?
最佳答案
如果您知道只想在装饰函数中使用该文件,那么最好使用 with
语句。此外,separator
是一个实现细节——我将它放在包装器之外:
def open_file(func):
def a_wrapper(filename, *args):
with open(filename, 'w') as f:
return func(f, *args)
return a_wrapper
此外,正如@Platinum Azure 指出的那样,使用 functools.wraps
总是一个好主意。对于您的装饰函数 - 这将确保包装函数的元数据存在于包装函数中(当您希望能够以编程方式区分包装函数时,这会很有用)。
编辑:
你应该将 separator
移出包装函数的原因是你可能有其他函数只需要一个文件对象而不需要分隔符。如果您创建这样的函数:
def say_hello(fp):
fp.write("Hello World!")
您不能使用 open_file
装饰器的一个版本,它也尝试将 separator
传递给 say_hello
- 尝试它会给你一个 TypeError
因为你正在尝试调用一个函数,它接受一个参数(一个文件对象)和两个参数 - 一个文件对象和一个分隔符。
此外,即使您所有的包装函数都至少需要一个额外的参数,它也不一定是分隔符。即使使用未经编辑的装饰器,这也是一个合法的包装函数:
def laugh(fp, number_of_times):
fp.write("Ha! " * number_of_times)
这就是我所说的 separator
是一个实现细节的意思。理想情况下,您的代码也是文档。如果您只使用此包装器写出由分隔符分隔的数据,那么您应该在包装器中保留分隔符参数,因为它有助于记录应该如何使用包装器。否则,第二个参数并不比第 14 个参数重要 - 不应使用其自己的参数调用。
关于python - 使用装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11589444/