我现在已经用几个例子思考这个问题了一段时间,我真的认为从方法代码内部直接引用方法对象或更一般地说:从内部引用命名空间会很方便。让我们看一下我当前的代码:
def do_stuff(args):
logtarget, someargs = process_input(args)
processed_data = do_other_stuff(someargs, outputdir)
log("Template string".format(processed_data), outputdir=outputdir, filename="resultfile.txt")
def do_other_stuff(someargs, logtarget):
step = process_data(someargs)
if requires_manual_postproceccing(step):
log(step, outputdir=outputdir, filename="handle manually.txt")
return get_result(step)
def log(message, outputdir="default", filename="default.txt"):
with open("{}/{}".format(outputdir, filename), "a") as file:
file.write(message)
正如你所看到的,我传递了outputdir很多次,我什至没有提到 do_stuff 和 do_other_stuff 也可能会记录一些东西(但因为只要脚本正常运行我就不需要这些日志,我不太关心它的位置)。如果可以设置一次参数,然后在日志消息中访问它,不是很好吗?目标由脚本处理,因此我无法对其进行硬编码。
由于outputdir是在函数(命名空间)内处理的,因此我们无法从其他函数(命名空间)访问它,除非我们使用glogal
关键字,这——毕竟我读过它——我希望永远不必使用。我的直觉告诉我要这样处理这个问题:
def do_stuff(args):
outputdir, someargs = process_input(args)
log.outputdir = outputdir
processed_data = do_other_stuff(someargs)
log(processed_data.format("somehow"), filename="resultfile.txt")
def do_other_stuff(someargs):
step = process_data(someargs)
if requires_manual_posproceccing(step):
log(step, filename="handle manually.txt")
return get_result(step)
def log(message, filename="default.txt"):
with open("{}/{}".format(this.outputdir, filename), "a") as file:
file.write(message)
它更容易阅读,使用更少的参数,并且不会引发奇怪的行为和错误 - 但它显然不起作用。现在我知道我可以(应该?)使用一个奇特的日志库或者至少编写一个记录器类,这样我就可以使用 logger = Logger(outputdir) 而不是使用 self在方法内部。但保持简洁和扁平是 Python 的编码方式,到目前为止,我可以轻松遵循以下规则:“只要你看到一个类具有 __init__
以外的方法,它就应该只是一个函数。”另外,即使我使用该记录器类或日志记录库,我仍然需要传递它的一个实例。
处理这个问题的最佳方法真的是使用方法的名称而不是 this
,并且当有人装饰我的函数时会面临问题,或者有没有办法直接引用当前的命名空间及其属性?要么我不知道搜索这个的正确词,要么它的级别太低而无法记录,或者它不存在。
[编辑:]实际上,我真正想做的(但不知道我想要它)是装饰(oop-cecorate,而不是Python的pie-decorate)log
函数。但我仍然会遇到同样的问题,因为 log = Decorate(log)
只会影响当前的命名空间。 dir
返回当前命名空间而不是全局命名空间,因此只要不想使用 global
,除了创建和传递可调用对象之外,确实没有其他方法对象(回调函数)。现在有两个答案,我无法轻易决定哪一个更清楚。可调用类suggested by Martin Bonner使用标准 Python 并仅创建一个可调用对象而不是两个。另一方面,我采用的解决方案是一个 get_log
函数,它返回一个函数,因为这样更清晰,避免创建一个仅使用 __init__
之外的方法的类并且需要更少的代码:
def get_log(outerdir):
def log(message, filename="default.txt"):
with open("{}/{}".format(outputdir, filename), "a") as file:
file.write(message)
return log
如果我们通过创建一个可以添加到任何函数的饼装饰器来使其更加通用,那么我们基本上只需重新创建 partial
函数 suggested by heemayl那么我们开始吧。最Pythonic的方法not invented here并使用最少的代码。
最佳答案
如果我理解正确,您正在寻找一种方法使 outputdir
对于所有可调用的 log
调用都是静态的。如果是这样,您可以利用 functools.partial
:
from functools import partial
log_with_outputdir = partial(log, outputdir='/path/to/outputdir')
现在您可以像 log
一样调用 log_with_outputdir
,而无需使用参数 outputdir
,因为它已被应用。
关于python - 有没有办法在 Python 中直接引用命名空间及其属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56992826/