我正在尝试获取班级中所有方法的名称。在测试检查模块的工作方式时,我提取了我的一种方法obj = MyClass.__dict__['mymethodname']
。
但是现在在inspect.ismethod(obj)
返回False
时inspect.isfunction(obj)
返回True
,我不明白为什么。是否有一些奇怪的方法将方法标记为我不知道的方法?我认为这只是它在类中定义并self
作为它的第一个参数。
您正在看到 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")
使用源
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')
好吧,你的意思是那obj.mymethod
是一个方法(隐式传递self
)Klass.__dict__['mymethod']
而是一个函数?
基本上Klass.__dict__['mymethod']
是“原始”函数,它可以通过称为描述符的东西转换为方法。这意味着类中的每个函数都可以是普通函数和方法,具体取决于您访问它们的方式。这就是类系统在 Python 中的工作方式,非常正常。
如果你想要方法,你不能去__dict__
(无论如何你都不应该去)。要获得所有你应该做的方法inspect.getmembers(Klass_or_Instance, inspect.ismethod)
您可以在此处阅读详细信息,有关此的说明在“用户定义的方法”下。
从对@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']
您可以使用dir获取可用方法/属性/等的名称,然后遍历它们以查看哪些是方法。像这样:
[ mthd for mthd in dir(FooClass) if inspect.ismethod(myFooInstance.__getattribute__(mthd)) ]
我期待有一个更清洁的解决方案,但如果没有其他人想出一个,这可能是你可以使用的东西。如果我不必使用类的实例来使用 getattribute,我会很高兴。