Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 分析所有类方法_Python_Design Patterns - Fatal编程技术网

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
,也令人困惑。再次感谢您的回答:-)