Python 分析所有类方法
我正在阅读《装饰师》杂志,我正在努力学习装饰师的概念。我一直停留在最后一个示例中,在这里我无法获得编写适用于类的所有方法的分析器的逻辑 。由于文案限制,我没有在这里重写,但我希望谷歌图书的链接足够了 问题是,当我实现代码并将其应用于我的Python 分析所有类方法,python,design-patterns,Python,Design Patterns,我正在阅读《装饰师》杂志,我正在努力学习装饰师的概念。我一直停留在最后一个示例中,在这里我无法获得编写适用于类的所有方法的分析器的逻辑 。由于文案限制,我没有在这里重写,但我希望谷歌图书的链接足够了 问题是,当我实现代码并将其应用于我的DoMathStuff类时,我得到TypeError:“NoneType”对象不可调用。对我来说,try/except/else部分不清楚,我认为某个地方有输入错误,但我可以知道在哪里 @profile_all_class_methods class DoMath
DoMathStuff
类时,我得到TypeError:“NoneType”对象不可调用。对我来说,try/except/else
部分不清楚,我认为某个地方有输入错误,但我可以知道在哪里
@profile_all_class_methods
class DoMathStuff(object):
"""docstring for DoMathStuff"""
def __init__(self, n):
self.n = n
def fib(self):
fPrev, f = 1, 1
for num in xrange(2, self.n):
fPrev, f = f, f + fPrev
return f
@profiling_decorator
def fact(self):
fct = 1
for num in xrange(1, self.n):
fct *= num
return fct
if __name__ == '__main__':
m = DoMathStuff(10)
print("Fib = {}, Fact = {}".format(m.fib(), m.fact()))
编辑:这是我得到的错误
Traceback (most recent call last):
File "class_profiler.py", line 62, in <module>
print("Fib = {}, Fact = {}".format(m.fib(), m.fact()))
TypeError: 'NoneType' object is not callable
回溯(最近一次呼叫最后一次):
文件“class_profiler.py”,第62行,在
打印(“Fib={},Fact={}”。格式(m.Fib(),m.Fact())
TypeError:“非类型”对象不可调用
这段代码确实充满了错误。只要考虑一下\uuuu getattribute\uuuu
方法的流程:给定一个属性名,我们在包装类上查找该属性(通过调用超类实现)。如果在那里找不到属性(在“fib”的情况下不是这样),因为它在包装类上,而不是包装器上,Python将引发AttributeError。好的,我们理解了这一点,这样我们就可以继续在包装类中查找它了。但是我们在EXPECT条款中做什么呢?没有什么。由于某种原因,代码位于else子句中,只有在未引发异常时才会调用该子句
因此,如果我们通过删除过程
并将代码从else
块中移动来解决这个问题,那么会怎么样?好了,现在需要获取self.inst
,即包装类的实例。但是你猜怎么着,获取一个属性将调用\uu getattribute\uu
方法。所以我们递归。现在,获取inst
属性的原始调用将成功。我们将其分配给x
。现在怎么办?呃,没什么。我们不返回x就退出了。因此,原始调用对self.inst
的值不获取任何值,并尝试调用\uuu getattribute\uuuu
,因此我们将获得另一个AttributeError
坦率地说,这段代码看起来像是由不太熟悉Python的人编写的。除了上述更改之外,还可以通过返回超类调用的值而不是分配它来修复它:
def __getattribute__(self, s):
try:
return super(ProfiledClass, self).__getattribute__(s)
except AttributeError:
x = self.inst.__getattribute__(s)
if type(x) == type(self.__init__):
return profiling_decorator(x)
else:
return x
但这仍然是相当糟糕的代码。首先,您不应该直接调用双下划线方法,因此except后面的行应该是x=getattr(self.inst,s)
。但问题远不止这些\uuuu getattribute\uuuuu
是一个完全错误的方法来覆盖。该方法用于所有属性查找,因此需要复杂的try/super/except。但是Python提供了一个方法,该方法仅在未直接找到属性时调用,即\uu getattr\uu
。相反,定义它将允许您完全删除大部分代码:
def __getattr__(self, s):
x = getattr(self.inst, s)
if type(x) == type(self.__init__):
return profiling_decorator(x)
else:
return x
(如果我真的很挑剔,我会用if callable(x)
替换type(x)==type(self.\uu init\uuu)
的东西)
这段代码中的最后一个错误是,当代码的全部要点是方法将被自动修饰时,它们将显式修饰。请显示完整的回溯。你确定你所有的缩进都是正确的吗?最后的return ProfiledClass
应该在类之外,但在def profile\u all\u class\u方法之内。正如您所提到的,我已经将return ProfiledClass
放在了正确的位置。我也仔细检查了一下,我想我一切都对了。我理解装饰师的逻辑。我看到这个类是非类型的,但我不明白为什么?你的担心是有道理的,但我认为这不是问题所在!书中有错误,这让我觉得这里也有错误。我已经在wrap\f
中修复了作者引用的n
中的一个,而他不应该这样做。你能试着分别调用m.fib()
和m.fact()
,看看是哪一个触发了错误吗?两者都会触发错误。不过,如果我不装饰教室,它们就很好用。非常感谢你的回答!我本来可以看出有什么不对劲的,但我没能弄明白。我注意到这本书中有很多错误,所以我的第一直觉是,这里有一些错误。关于\uuuu getattr\uuuu
,我也很好奇,因为我在其他示例中看到了它的使用,然后突然出现了\uuuu getattribute\uuuuu
,增加了更多的混乱。书中到处都是装饰过的
factorial
,也令人困惑。再次感谢您的回答:-)