我正在阅读Practical Python Design Patterns,我正在努力学习decorator的概念。我一直停留在最后一个示例中,无法获得编写适用于类的所有方法的探查器的逻辑。你知道吗
Here is at the example from the book。我没有在这里重写它,因为文案限制,但我希望谷歌图书的链接是足够的。你知道吗
问题是,当我实现代码并将其应用于我的DoMathStuff
类时,我得到了TypeError: 'NoneType' object is not callable
。对我来说,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
这段代码确实充满了错误。想想
__getattribute__
方法的流程:给定一个属性名,我们在包装类上查找属性(通过调用超类实现)。如果在那里找不到属性-在“fib”的情况下不是这样的,因为它在包装类上,而不是包装器上-Python将引发AttributeError。好的,我们捕捉到它,大概是为了我们可以继续在包装的类中查找它。但是在EXPECT子句中我们该怎么做呢?没有什么。由于某种原因,代码在else子句中,只有在引发异常而不是时才调用该子句。你知道吗那么,如果我们通过移除
pass
并将代码从else
块中移除来修复这个问题,那么会怎样呢?好吧,现在需要得到self.inst
,即包装类的实例。但是你猜怎么着,获取一个属性会调用__getattribute__
方法。所以我们重复。现在,获取inst
属性的原始调用将成功。我们把它赋给x
。现在怎么办?呃,没什么。我们在不返回x的情况下退出。因此,原始调用对self.inst
的值获取None,并尝试对该值调用__getattribute__
,因此我们将获得另一个AttributeError。你知道吗坦率地说,这段代码看起来像是由一个不太了解Python的人编写的。除了上面的更改之外,还可以通过返回超类调用的值而不是赋值来修复它:
但这仍然是相当糟糕的代码。首先,您不应该直接调用双下划线方法,因此except后面的行应该是
x = getattr(self.inst, s)
。但问题远不止于此;__getattribute__
首先是完全错误的重写方法。所有属性查找都会调用该方法,因此需要复杂的try/super/except。但是Python提供了一个方法,该方法只在而不是直接找到属性时调用,即__getattr__
。相反,定义它将允许您完全删除大部分代码:(如果我真的很挑剔,我会用
if callable(x)
来代替type(x) == type(self.__init__)
的东西。)这段代码中的最后一个错误是,它们将
factorial
显式修饰,而代码的要点是方法将被自动修饰。你知道吗相关问题 更多 >
编程相关推荐