查找方法内部的方法数,并分别访问每个方法

时间:2014-12-01 20:55:46

标签: python function class python-2.7 methods

我在一个调用方法列表的类中有一个方法def testing(self)。我需要知道是否有任何方法可以获得方法中调用的方法总数,然后分别访问每个方法。

def testing(self):
    self.method1()
    self.method2()
    self.method3()
    return

def method1(self):
    """DO WORK"""
    return

def method2(self):
    """DO WORK"""
    return

def method3(self):
    """DO WORK"""
    return

1 个答案:

答案 0 :(得分:1)

可靠且稳健吗?否。

有两种基本方法:

  • 动态地:用计算调用的东西模拟方法,然后调用方法。
  • 静态:在代码中查找方法调用,而不调用它。

模拟至少具有潜在的破坏性,而且它很脆弱,而且可能很复杂。但最大的问题是它只能在所调用的路径上找到方法调用。例如,让我们说你写了这个:

def testing(self):
    if self.method1():
        return self.method2()
    else:
        return self.method3(self.method4())

显然,没有电话会找到所有四个方法调用。

或者:

def testing(self):
    return 2 / self.method1()

除非您事先知道method1必须在此上下文中返回一个数字,否则您将在此处获得TypeError。但如果你知道这一点,你可能已经知道在这种情况下调用method1,所以你的问题甚至不存在。

无论如何,因为模拟在概念层面上已经足够困难而不必处理所有实现难题,正确的方法是使用第三方模块,如Michele d'Amico's answer所示。但是如果你想了解它是如何工作的,你可以自己快速建立一些东西:

def mock(method, *args, **kwargs):
    obj = method.__self__
    _old_getattribute = type(obj).__getattribute__
    methods = []
    def _new_getattribute(self, attr):
        methods.append(attr)
    type(obj).__getattribute__ = _new_getattribute
    try:
        method(*args, **kwargs)
    except Exception as e:
        print 'Ignoring {}: {}'.format(type(e), e)
    type(obj).__getattribute__ = _old_getattribute
    return [name for name in methods if callable(getattr(obj, name))]

methods = mock(self.testing)

除了上面提到的问题之外,这本身就假定在方法调用过程中self上查找的任何内容实际存在,并且任何可调用的内容(包括例如{{1}或者在实例属性中填充的常规函数​​)是一种方法。你几乎必须仔细思考所有这些问题,决定你想要什么,并实现它。


同时,有多种方法可以查看代码。您可以解析源代码(例如,使用inspect.getsource),或者您可以对staticmethod中的字节码进行grub。 (Bytecode当然是不可移植的。)但幸运的是,stdlib有两个模块来帮助你:dis来反汇编字节码,或ast模块来解析源代码。 testing.__code__.co_code的2.x版本使用起来有点笨拙;它没有给你任何方法来迭代字节码并访问它们的参数等。你仍然可以通过解析字符串输出或使用各种第三方模块来完成它。

无论如何,你需要提出一些关于什么算作"方法调用的规则"并编写代码来识别该模式。当然,模拟版本也是如此,但是这个版本更加明显。

以下是dis的示例,该示例可以查找直接在ast之外访问的任何内容:

self