我的目标是创建一个简单的日志模块,其中包含一个日志类,我可以在其他项目中使用它来跟踪事件。特别是,我想创建一个“@tracemethod”装饰器来记录所有方法调用(方法名和参数)。下面是该类的一个非常简化(但功能性)的版本:
class Log :
def __init__(self, path) :
self.path = path
# here is a whole path-checking routine.
def log(self, msg):
with open(self.path, mode="a+") as log_file :
log_file.write(msg + "\n")
def tracemethod(self, f):
def wrapped(self2, *args, **kwargs) :
outstring = "{}({},{})".format(f.__name__, str(args), str(kwargs))
self.log(outstring)
return f(self2, *args, **kwargs)
return wrapped
我可以调用其他模块中的类并使用它:
from log import Log
log1 = Log("/Path/to/existing_log_file.txt")
class Foo() :
@log1.tracemethod
def __init__(self, a, b, c) :
self.a = a
self.b = b
self.c = c
@log1.tracemethod
def a_method(self, c, d, e):
return c+d+e
foo = Foo(4,5, c=5 )
foo.a_method(32, 64, e=9)
在现有的日志中_文件.txt地址:
__init__((4, 5),{'c': 5})
a_method((32, 64),{'e': 9})
但是如您所见,Log类中的“tracemethod”方法使用“self2”参数来区分Log实例和使用它的Foo实例。我听说改名“self”是一个很大的禁忌。什么是正确的/Python式的方法来实现这一点?你知道吗
当您实际需要访问包装的
self
时,这有点进退两难,因为有一条准则告诉您不要重命名任何一个self
参数,但有一条更强大的准则告诉您不要用另一个self
来隐藏一个self
。你知道吗在pep8中没有什么可以告诉你该做什么;文档中甚至没有一个例子。你知道吗
但这是有原因的。实际上,很少需要访问包装的
self
。看看你的代码:你不会对self2
做任何事情:显然,您确实希望在输出中跳过它,但是您可以通过切片
[1:]
来完成。因此,就像文档中的所有示例一样,将其保留在*args
中,而不是将其作为单独的参数取出:所以,在你的情况下,问题避免了。你知道吗
当你不能侥幸逃脱时怎么办?你知道吗
在这种情况下,似乎没有一个被广泛接受的标准。说真的,任何能清楚表明哪个自我是哪个自我的东西,并且能很容易地从视觉上区分两者的东西,都是可以的;
self2
并不能很好地解决这个问题,但阿马达农的wrappedself
确实做到了。你知道吗我认为我见过的两个最常见的名字是
inner_self
和wrapped_self
(带下划线或不带下划线),但如果不做更科学的调查,我不会太依赖于这一点。你知道吗我也看过一个教程(虽然我不记得在哪里),它建议在另一个函数调用中包装所有内容,只是为了避免出现问题,但这在我看来是相当愚蠢的。你知道吗
我认为最具python风格的方法是完全跳过内在的“self”,只需使用*args和**args(如果需要,args[0]将是“self”):
毕竟,self是一个参数。这样,您的decorator也可以处理常规(非对象)函数。你知道吗
或者,用“wrappedself”替换“self”(或者类似的东西)怎么样,然后你可以用“self”代替“self2”:
相关问题 更多 >
编程相关推荐