关于Python:Python – 如何查询定义方法的类?

Python - How can I query the class in which a method is defined?

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

我需要这样做,因为我的子类定义了"宏"方法,它在更高的抽象级别上访问父类的方法,而且我不希望用户担心继承树上定义的较低级别的方法。

下面是一个简单的例子:

1
2
3
4
5
6
7
8
9
10
11
12
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)

输出:

1
2
3
4
5
[('__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__属性?更好的是,是否可以对实例方法执行相同的操作?


方法有一个im_class属性,它指向相关的类。可以对属于类成员的函数使用该筛选器:

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

这给了你:

1
2
3
4
5
[
    ('__init__', <unbound method Bar.__init__>),
    ('f1', <unbound method Bar.f1>),
    ('f2', <unbound method Bar.f2>)
]

当然,你可以直接绕过getmembers,然后:

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

给予:

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

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

这些"秘密"属性都记录在Python数据模型中。


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

1
2
3
4
foo_members = inspect.getmembers(Foo,inspect.ismethod)
bar_members = inspect.getmembers(Bar,inspect.ismethod)

set(bar_members) - set(foo_members)

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

例如。:

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