Python:inspect.ismethod 是如何工作的?
Posted
技术标签:
【中文标题】Python:inspect.ismethod 是如何工作的?【英文标题】:Python: how does inspect.ismethod work? 【发布时间】:2011-03-14 19:24:36 【问题描述】:我正在尝试获取班级中所有方法的名称。
在测试检查模块的工作方式时,我通过obj = MyClass.__dict__['mymethodname']
提取了我的一种方法。
但是现在inspect.ismethod(obj)
返回False
而inspect.isfunction(obj)
返回True
,我不明白为什么。是否有一些奇怪的方法将方法标记为我不知道的方法?我以为只是它在类中定义并以self
作为它的第一个参数。
【问题讨论】:
【参考方案1】:您正在看到 Python 的幕后机制的一些效果。
当您编写f = MyClass.__dict__['mymethodname']
时,您会得到“mymethodname”的原始实现,这是一个普通函数。要调用它,您需要传入一个附加参数,即类实例。
当您编写f = MyClass.mymethodname
时(注意mymethodname 后面没有括号),您会得到一个MyClass 类的未绑定方法,它是MethodType
的一个实例,它包装了您在上面获得的原始函数。要调用它,您需要传入一个附加参数,即类实例。
当您编写f = MyClass().mymethodname
时(请注意,在获取方法之前我已经创建了MyClass 类的对象),您将获得MyClass 类实例的绑定方法。您不需要向它传递额外的类实例,因为它已经存储在其中。
要通过以字符串形式给出的名称获取包装方法(绑定或未绑定),请使用getattr
,如gnibbler 所述。例如:
unbound_mth = getattr(MyClass, "mymethodname")
或
bound_mth = getattr(an_instance_of_MyClass, "mymethodname")
【讨论】:
【参考方案2】:使用the source
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')
【讨论】:
【参考方案3】:嗯,你的意思是obj.mymethod
是一个方法(隐式传递self
)而Klass.__dict__['mymethod']
是一个函数?
基本上Klass.__dict__['mymethod']
是“原始”函数,可以通过称为描述符 的东西转换为方法。这意味着类中的每个函数既可以是普通函数,也可以是方法,这取决于您访问它们的方式。这就是类系统在 Python 中的工作方式,非常正常。
如果你想要方法,你不能通过__dict__
(无论如何你都不应该这样做)。要获取所有方法,您应该执行inspect.getmembers(Klass_or_Instance, inspect.ismethod)
您可以阅读details here,有关此的说明在“用户定义的方法”下。
【讨论】:
当我创建一个继承自内置 python 类的类时,有没有办法只获取用户定义的方法?查看__dict__
似乎可行,但您说不应该这样做。还有其他方法吗?
@Eskil - 查看__dict__
不适用于没有__dict__
的类(“新式类”默认情况下没有它),或者将无法正常工作具有它但未在__dict__
中反映其属性的类(可能是由扩展定义的类和一些内置类的情况)。使用inspect.getmembers
,如上图。
但是 inspect.getmembers(Klass_or_Instance, inspect.ismethod) ,如上所述,提供所有方法,而不仅仅是用户定义的方法。查看 method.__module__ 是否与我自己的模块匹配是否安全?
它查看一个对象并为您提供所有作为方法的成员(duh)。你究竟想要什么?只有在给定类上定义的成员?【参考方案4】:
从对@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']
【讨论】:
啊,是的,如果我让类继承自“纯”python 类,这就是我所需要的。但是假设我想创建一个 unittest.TestCase 的子类,并且想区分我自己的新方法和 TestCase 方法?这在这种情况下不起作用,因为这两种类型都从 inspect.ismethod 返回 True。【参考方案5】:您可以使用 dir 来获取可用方法/属性/等的名称,然后遍历它们以查看哪些是方法。像这样:
[ mthd for mthd in dir(FooClass) if inspect.ismethod(myFooInstance.__getattribute__(mthd)) ]
我期待有一个更清洁的解决方案,但如果没有其他人想出一个,这可能是你可以使用的东西。如果我不必使用类的实例来使用 getattribute,我会很高兴。
【讨论】:
以上是关于Python:inspect.ismethod 是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章