如何在不积极修改代码的情况下扩展日志记录? [写干净的代码]

时间:2019-02-03 03:12:19

标签: python design-patterns coding-style

比方说,我有一个calculate()方法,而我想记录下来的是在不同的阶段变量的值,这与很多变量计算复杂(编辑:不仅为验证,但对数据的研究目的) 。例如。

# These assignment are arbitrary, 
# but my calculate() method is more complex
def calculate(a, b):
  c = 2*a+b
  d = a-b
  if c > d+10:
    g = another_calc(a, c):
  else:
    g = another_calc(a, d):
  return c, d, g

def another_calc(a, c_d):
  e = a+c_d
  f = a*c_d
  g = e+f
  return g

您可能会假设该方法将进行大量修改以进行实验探索。 这里没有太多日志记录,我想记录下发生的事情,例如,我可以编写像这样的激进代码

# These assignment are arbitrary, 
# but my calculate() method is more complex
def calculate(a, b):
  info = {"a": a, "b": b}
  c = 2*a+b
  d = a-b
  info["c"], info["d"] = c, d
  if c > d+10:
    info["switch"] = "entered c"
    g, info = another_calc(a, c, info):
  else:
    info["switch"] = "entered d"
    g, info = another_calc(a, d, info):
  return c, d, g, info

def another_calc(a, c_d, info):
  e = a+c_d
  f = a*c_d
  g = e+f
  info["e"], info["f"], info["g"] = e, f, g
  return g, info

这为我的目的(我得到的信息对象,然后将它导出为CSV我进一步研究) 但是将更多(非功能性)行添加到原始的干净calculate()方法中,更改签名和返回值是很丑陋的。

但是我可以编写更简洁的代码吗? 我想是否可以用装饰来包装这个方法。希望你们能得到一些好的答案。谢谢。

1 个答案:

答案 0 :(得分:0)

一种编写更简洁的代码的方法(我认为)是将info -dictionary包装在一个类中。

这是我的简单代码示例:

-Wl,--verbose

利弊

我在这里使用单独的记录器类,因为这样我就不需要知道记录器是如何实现的。在该示例中,它只是一个简单的字典,但是如果需要,您可以更改创建新记录器的实现。

此外,您还可以选择如何打印数据或选择输出。也许您可以拥有Logger的界面。

我使用了字典,因为它看起来像只需要键值对。

现在,使用记录器,我们需要更改方法签名。当然,例如,您可以将默认值定义为“无”。然后应始终检查None值,这就是为什么我没有定义默认值。如果您拥有代码,并且可以更改-nostdlib方法的每个引用,那么应该没有问题。

还有一件有趣的事情,以后可能会变得很重要。调试输出后,无需再记录任何内容,则只需实现Null object。使用# These assignment are arbitrary, # but my calculate() method is more complex def calculate(a, b, logger): logger.log("a", a) logger.log("b", b) c = 2*a+b d = a-b logger.log("c", c) logger.log("d", d) if c > d+10: logger.log("switch", "entered c") g = another_calc(a, c) else: logger.log("switch", "entered d") g = another_calc(a, d) return c, d, g def another_calc(a, c_d, logger): e = a+c_d f = a*c_d g = e+f logger.log("e", e) logger.log("f", f) logger.log("g", g) return g class Logger(object): data = [] def log(self, key, value): self.data.append({key: value}) def getLog(self): return self.data logger = Logger() print(calculate(4, 7, logger)) print(logger.getLog()) ,您可以删除所有日志记录而无需再次更改代码。

我试图思考如何使用装饰器,但现在找到了任何好的方法。如果只记录输出,则装饰器可以工作。