我有许多以下形式的函数:
def parse_file_1(file_name)
# do something generic
with open(file_name) as f:
for line in f:
# do some generic things with line
# do some things specific to parse_file_1 with line
为了避免重复大量代码,我使用装饰器重写了它:
def parse_file(parse_function):
def _parse_file(file_name):
# do something generic
with open(file_name) as f:
for line in f:
# do some generic things with line
parse_function(line)
return _parse_file
@parse_file
def parse_file_1(line):
# do some things specific to parse_file_1 with line
这工作得很好 - 这两个版本在功能上是相同的,正如预期的那样,并且很容易编写这种形式的新函数,而无需复制和粘贴通用代码。
但是,装饰器 parse_file
更改了 parse_file_1
的签名,这让 PyCharm 感到困惑(它认为 parse_file_1
具有签名 (line)
而不是 (file_name)
),并且通常很难确定 parse_file_1
的签名。
这种做法有多糟糕?(如果很糟糕)有什么好的替代方案(理想情况下不需要太多重复的代码)?或者,让 PyCharm 知道 parse_file_1
的真实签名的方法将消除我对当前情况的最大问题。
最佳答案
我不会为此使用装饰器。相反,将解析器函数传递给一个高阶生成器怎么样?
def parse_using(file_name, func):
with open(file_name) as f:
for line in f:
yield func(line)
def parse_foo_line(line):
return 'This line is very foo-ey: ' + line
parsed_foo = parse_using('foo.txt', parse_foo_line)
parsed_bar = parse_using('bar.txt', parse_bar_line) # etc...
请注意,这些函数是生成器,因此在迭代之前它们实际上不会解析任何内容(即使如此,它们也只返回一次结果)。如果您想急切地解析事物,请转换为列表。
parsed_foo = list(parse_using('foo.txt', parse_foo_line))
关于python - 改变签名的装饰器是一个不好的模式吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51857799/