14

我正在尝试获取班级中所有方法的名称。在测试检查模块的工作方式时,我提取了我的一种方法obj = MyClass.__dict__['mymethodname']

但是现在在inspect.ismethod(obj)返回Falseinspect.isfunction(obj)返回True,我不明白为什么。是否有一些奇怪的方法将方法标记为我不知道的方法?我认为这只是它在类中定义并self作为它的第一个参数。

4

5 回答 5

11

您正在看到 Python 的幕后机制的一些效果。

当您编写时f = MyClass.__dict__['mymethodname'],您会得到“mymethodname”的原始实现,这是一个普通函数。要调用它,您需要传入一个附加参数,即类实例。

当您编写时(注意 mymethodname 后面没有括号),您会得到一个 MyClass 类的未绑定方法,它是包装了您在上面获得的原始函数f = MyClass.mymethodname的一个实例。MethodType要调用它,您需要传入一个附加参数,即类实例。

当您编写时f = MyClass().mymethodname(请注意,在采用 MyClass 的方法之前,我已经创建了一个 MyClass 类的对象),您将获得一个 MyClass 类实例的绑定方法。您不需要向它传递额外的类实例,因为它已经存储在其中。

要通过以字符串形式给出的名称获取包装方法(绑定或未绑定),请使用getattr,如gnibbler 所述。例如:

unbound_mth = getattr(MyClass, "mymethodname")

或者

bound_mth = getattr(an_instance_of_MyClass, "mymethodname")
于 2010-07-12T13:23:34.180 回答
3

使用

def ismethod(object):
    """Return true if the object is an instance method.
    Instance method objects provide these attributes:
        __doc__         documentation string
        __name__        name with which this method was defined
        __func__        function object containing implementation of method
        __self__        instance to which this method is bound"""
    return isinstance(object, types.MethodType)

第一个论点self只是按照惯例。通过从类的字典中按名称访问方法,您绕过了绑定,因此它似乎是一个函数而不是一个方法

如果您想按名称访问该方法,请使用

getattr(MyClass, 'mymethodname') 
于 2010-07-12T13:06:27.130 回答
1

好吧,你的意思是那obj.mymethod是一个方法(隐式传递selfKlass.__dict__['mymethod']而是一个函数?

基本上Klass.__dict__['mymethod']是“原始”函数,它可以通过称为描述符的东西转换为方法。这意味着类中的每个函数都可以是普通函数和方法,具体取决于您访问它们的方式。这就是类系统在 Python 中的工作方式,非常正常。

如果你想要方法,你不能去__dict__(无论如何你都不应该去)。要获得所有你应该做的方法inspect.getmembers(Klass_or_Instance, inspect.ismethod)

您可以在此处阅读详细信息,有关此的说明在“用户定义的方法”下。

于 2010-07-12T13:10:11.010 回答
1

从对@THC4k 答案的评论来看,OP 似乎想要区分内置方法和纯 Python 代码中定义的方法。用户定义的方法属于types.MethodType,但内置方法不是。

您可以像这样获得各种类型:

import inspect
import types

is_user_defined_method = inspect.ismethod

def is_builtin_method(arg):
    return isinstance(arg, (type(str.find), type('foo'.find)))

def is_user_or_builtin_method(arg):
    MethodType = types.MethodType
    return isinstance(arg, (type(str.find), type('foo'.find), MethodType))

class MyDict(dict):
    def puddle(self): pass

for obj in (MyDict, MyDict()):
    for test_func in (is_user_defined_method, is_builtin_method,
            is_user_or_builtin_method):
        print [attr 
            for attr in dir(obj)
            if test_func(getattr(obj, attr)) and attr.startswith('p')]

打印:

['puddle']
['pop', 'popitem']
['pop', 'popitem', 'puddle']
['puddle']
['pop', 'popitem']
['pop', 'popitem', 'puddle']
于 2010-07-12T16:37:25.567 回答
0

您可以使用dir获取可用方法/属性/等的名称,然后遍历它们以查看哪些是方法。像这样:

[ mthd for mthd in dir(FooClass) if inspect.ismethod(myFooInstance.__getattribute__(mthd)) ]

我期待有一个更清洁的解决方案,但如果没有其他人想出一个,这可能是你可以使用的东西。如果我不必使用类的实例来使用 getattribute,我会很高兴。

于 2010-07-12T13:07:50.183 回答