分析所有类方法

2024-06-26 13:39:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在阅读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

Tags: theinselfforobjectisdefdecorator
1条回答
网友
1楼 · 发布于 2024-06-26 13:39:28

这段代码确实充满了错误。想想__getattribute__方法的流程:给定一个属性名,我们在包装类上查找属性(通过调用超类实现)。如果在那里找不到属性-在“fib”的情况下不是这样的,因为它在包装类上,而不是包装器上-Python将引发AttributeError。好的,我们捕捉到它,大概是为了我们可以继续在包装的类中查找它。但是在EXPECT子句中我们该怎么做呢?没有什么。由于某种原因,代码在else子句中,只有在引发异常而不是时才调用该子句。你知道吗

那么,如果我们通过移除pass并将代码从else块中移除来修复这个问题,那么会怎样呢?好吧,现在需要得到self.inst,即包装类的实例。但是你猜怎么着,获取一个属性会调用__getattribute__方法。所以我们重复。现在,获取inst属性的原始调用将成功。我们把它赋给x。现在怎么办?呃,没什么。我们在不返回x的情况下退出。因此,原始调用对self.inst的值获取None,并尝试对该值调用__getattribute__,因此我们将获得另一个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)。但问题远不止于此;__getattribute__首先是完全错误的重写方法。所有属性查找都会调用该方法,因此需要复杂的try/super/except。但是Python提供了一个方法,该方法只在而不是直接找到属性时调用,即__getattr__。相反,定义它将允许您完全删除大部分代码:

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.__init__)的东西。)

这段代码中的最后一个错误是,它们将factorial显式修饰,而代码的要点是方法将被自动修饰。你知道吗

相关问题 更多 >