Python - 如何查询定义方法的类?

时间:2012-08-13 12:22:22

标签: python methods introspection inspect

我的问题与this one有些相似;它涉及对象方法而不是模块内容。我想知道我是否可以使用inspect模块来获取仅在我询问的类中定义的方法,而不是它的父类。

我需要这个,因为我的子类定义了'宏'方法,它在更高的抽象级别访问父方法,我不希望用户不得不担心一直定义的低级方法继承树。

这是一个简化的例子:

class Foo(object):
    def __init__(self): pass
    def f1(self): return 3
    def f2(self): return 1

class Bar(Foo):
    def __init__(self): Foo.__init__(self)
    def g1(self): return self.f1() + self.f2()
    def g2(self): return self.f1() - self.f2()

import inspect
inspect.getmembers(Bar, inspect.ismethod)

输出:

[('__init__', <unbound method Bar.__init__>),
 ('f1', <unbound method Bar.f1>),
 ('f2', <unbound method Bar.f2>),
 ('g1', <unbound method Bar.g1>),
 ('g2', <unbound method Bar.g2>)]

用户不需要知道或关心f的存在,因为她只对g感兴趣。 (当然,这个输出在绝大多数上下文中都是有意义的,因为所有这些方法在实例化时都会被绑定到对象。)对于一个长继承树,返回的列表可以变得很长并且充满了所有的东西。与用户相关。

如何让它离开此列表f1f2?是否有类似于类中定义的方法的__module__属性?更好的是,是否可以使用实例方法做同样的事情?

2 个答案:

答案 0 :(得分:5)

方法有一个im_class属性,指向有问题的类。您可以对属于该类成员的函数使用该过滤器:

inspect.getmembers(Bar,
    lambda m: inspect.ismethod(m) and m.__func__ in m.im_class.__dict__.values())

这会给你:

[
    ('__init__', <unbound method Bar.__init__>),
    ('f1', <unbound method Bar.f1>), 
    ('f2', <unbound method Bar.f2>)
]

当然,你可以完全绕过getmembers

[m for m in Bar.__dict__.values() if inspect.isfunction(m)]

给出:

[<function __init__ at 0x100a28de8>, <function g1 at 0x100a28e60>, <function g2 at 0x100a28ed8>]

这适用于绑定或未绑定方法,它们具有相同的.__func__(或im_func,旧名称)属性。 bound和unbound之间的区别是.__self__属性的值(未绑定时为None)。

这些“秘密”属性都记录在Python Data Model

答案 1 :(得分:2)

希望有人会提出更好的解决方案,但是:

foo_members = inspect.getmembers(Foo,inspect.ismethod)
bar_members = inspect.getmembers(Bar,inspect.ismethod)

set(bar_members) - set(foo_members)

当然,在实际情况中,你可能需要走过Bar.__bases__才能真正摆脱你不想要的一切。

e.g:

set(bar_members) - set(sum([inspect.getmembers(base,inspect.ismethod) for base in Bar.__bases__],[]))