在源代码中查找派生类

时间:2013-01-31 18:55:55

标签: python abstract-syntax-tree

我有一个包含python代码的文件。我需要检查它(没有导入或运行它,虽然编译它没问题。)

我想在文件中声明Classes,看看它们是否来自某个基类。

例如,

在我的'foo'模块中,我有一个名为'Bar'的类,它派生自'Foo'类:

class Foo(object):
    pass

class Bar(Foo)
    pass

然后我有一个外部python源文件,例如:

from foo import Bar

class Baz(Bar):
    pass

我想检查源代码以了解该文件是否包含从我的'Foo'派生的任何类定义。

我需要解析AST吗?这是否是对子类定义进行静态分析的正确方向?

2 个答案:

答案 0 :(得分:1)

不编译代码的答案是使用pysmell或类似代码。

鉴于:

# base.py
class Base(object):
    def __init__(self, name):
        self.name = name

class First(Base):
    def __init__(self, name="first"):
        super(First, self).__init__(name)


class Second(First):
    def __init__(self, name="second"):
        super(Second, self).__init__(name)

class Third(Second):
    def __init__(self, name="third"):
        super(Third, self).__init__(name)

t = Third()

运行pysmell base.py生成一个PYSMELLTAGS文件,如下所示:

{'CLASSES': {'base.Base': {'bases': ['object'],
                           'constructor': ['name'],
                           'docstring': '',
                           'methods': [],
                           'properties': ['name']},
             'base.First': {'bases': ['base.Base'],
                            'constructor': ["name='first'"],
                            'docstring': '',
                            'methods': [],
                            'properties': []},
             'base.Second': {'bases': ['base.First'],
                             'constructor': ["name='second'"],
                             'docstring': '',
                             'methods': [],
                             'properties': []},
             'base.Third': {'bases': ['base.Second'],
                            'constructor': ["name='third'"],
                            'docstring': '',
                            'methods': [],
                            'properties': []}},
 'CONSTANTS': ['base.t'],
 'FUNCTIONS': [],
 'HIERARCHY': ['base'],
 'POINTERS': {}}

我认为这将有助于OP实现识别派生自其他类的类的目标。

答案 1 :(得分:-1)

我认为这样的事情可以,因为它只会污染x

import inspect
from tester import Test

x = __import__("something", globals={}, locals={})

for (n,v) in inspect.getmembers(x):
    if inspect.isclass(v):
        print "CLASS:", n, inspect.getmro(v)
        if Test != v and Test in inspect.getmro(v):
            print "FOUND:", n, v


 #something.py
 from tester import Test
 class SomeClass(Test): pass


 #tester.py
 class Test(object): pass

输出:

CLASS: SomeClass (<class 'something.SomeClass'>, <class 'tester.Test'>, <type 'object'>)
FOUND: SomeClass <class 'something.SomeClass'>
CLASS: Test (<class 'tester.Test'>, <type 'object'>)