12

在 Python 中,我需要有效且通用地测试类的属性是否是实例方法。调用的输入将是被检查属性的名称(字符串)和对象。

无论属性是否是实例方法,hasattr 都会返回 true。

有什么建议么?


例如:

class Test(object):
    testdata = 123

    def testmethod(self):
        pass

test = Test()
print ismethod(test, 'testdata') # Should return false
print ismethod(test, 'testmethod') # Should return true
4

5 回答 5

17
def hasmethod(obj, name):
    return hasattr(obj, name) and type(getattr(obj, name)) == types.MethodType
于 2009-07-07T09:33:55.020 回答
7

您可以使用该inspect模块:

class A(object):
    def method_name(self):
        pass


import inspect

print inspect.ismethod(getattr(A, 'method_name')) # prints True
a = A()
print inspect.ismethod(getattr(a, 'method_name')) # prints True
于 2009-07-07T09:35:20.990 回答
6
import types

print isinstance(getattr(your_object, "your_attribute"), types.MethodType)
于 2009-07-07T09:32:10.343 回答
4

该函数检查属性是否存在,然后检查该属性是否是使用inspect模块的方法。

import inspect

def ismethod(obj, name):
    if hasattr(obj, name):
        if inspect.ismethod(getattr(obj, name)):
            return True
    return False

class Foo:
    x = 0
    def bar(self):
        pass

foo = Foo()
print ismethod(foo, "spam")
print ismethod(foo, "x")
print ismethod(foo, "bar")
于 2009-07-07T09:35:49.447 回答
0

请注意@classmethod-decorated 函数将通过其他答案中的所有测试。您希望这些被视为“实例方法”吗?也许这只是语义,但根据定义,它们对类进行操作,而不是生成的实例。我不确定 hasmethod2 (我提出的解决方案)失败的情况,但至少它可以警惕类方法:


import inspect
import types

def hasmethod(obj, name):
    return hasattr(obj, name) and type(getattr(obj, name)) == types.MethodType

def hasmethod2(obj, name):
    try:
        attr = getattr(obj, name)
        return not inspect.isclass(attr.__self__)
    except AttributeError:
        return False

class Test(object):
    testdata = 123

    def testmethod(self):
        pass

    @classmethod
    def testmethod2(cls):
        pass

# Returns True. This may be undesired depending on your definition of 'instance method'
hasmethod(Test(), 'testmethod2')
 
# Returns False
hasmethod2(Test(), 'testmethod2')

它之所以有效,__self__是因为绑定到主要调用参数(类方法的类实例,普通属性的对象实例,模块或各种内置函数的任何内容)。因此,检查类的存在__self____self__非类分别排除了非函数属性和类方法。

于 2021-05-13T18:49:37.177 回答