Python:inspect.ismethod 如何工作?

发布于 2024-09-09 05:48:12 字数 284 浏览 11 评论 0原文

我正在尝试获取类中所有方法的名称。 在测试检查模块如何工作时,我通过 obj = MyClass.__dict__['mymethodname'] 提取了我的方法之一。

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

I'm trying to get the name of all methods in my class.
When testing how the inspect module works, i extraced one of my methods by obj = MyClass.__dict__['mymethodname'].

But now inspect.ismethod(obj) returns False while inspect.isfunction(obj) returns True, and i don't understand why. Is there some strange way of marking methods as methods that i am not aware of? I thought it was just that it is defined in the class and takes self as its first argument.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

自此以后,行同陌路 2024-09-16 05:48:12

您正在看到 Python 幕后机制的一些影响。

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

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

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

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

unbound_mth = getattr(MyClass, "mymethodname")

bound_mth = getattr(an_instance_of_MyClass, "mymethodname")

You are seeing some effects of the behind-the-scenes machinery of Python.

When you write f = MyClass.__dict__['mymethodname'], you get the raw implementation of "mymethodname", which is a plain function. To call it, you need to pass in an additional parameter, class instance.

When you write f = MyClass.mymethodname (note the absence of parentheses after mymethodname), you get an unbound method of class MyClass, which is an instance of MethodType that wraps the raw function you obtained above. To call it, you need to pass in an additional parameter, class instance.

When you write f = MyClass().mymethodname (note that i've created an object of class MyClass before taking its method), you get a bound method of an instance of class MyClass. You do not need to pass an additional class instance to it, since it's already stored inside it.

To get wrapped method (bound or unbound) by its name given as a string, use getattr, as noted by gnibbler. For example:

unbound_mth = getattr(MyClass, "mymethodname")

or

bound_mth = getattr(an_instance_of_MyClass, "mymethodname")
噩梦成真你也成魔 2024-09-16 05:48:12

使用

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)

第一个参数是 < code>self 只是按照惯例。通过从类的字典中按名称访问方法,您将绕过绑定,因此它看起来是一个函数而不是方法

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

getattr(MyClass, 'mymethodname') 

Use 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)

The first argument being self is just by convention. By accessing the method by name from the class's dict, you are bypassing the binding, so it appears to be a function rather than a method

If you want to access the method by name use

getattr(MyClass, 'mymethodname') 
脱离于你 2024-09-16 05:48:12

好吧,你的意思是 obj.mymethod 是一个方法(隐式传递 self),而 Klass.__dict__['mymethod'] 是一个功能?

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

如果您想要方法,则不能使用 __dict__ (无论如何您都不应该这样做)。要获取所有方法,您应该执行inspect.getmembers(Klass_or_Instance,inspect.ismethod)

您可以阅读详细信息在这里,关于这个的解释在“用户定义的方法”下。

Well, do you mean that obj.mymethod is a method (with implicitly passed self) while Klass.__dict__['mymethod'] is a function?

Basically Klass.__dict__['mymethod'] is the "raw" function, which can be turned to a method by something called descriptors. This means that every function on a class can be both a normal function and a method, depending on how you access them. This is how the class system works in Python and quite normal.

If you want methods, you can't go though __dict__ (which you never should anyways). To get all methods you should do inspect.getmembers(Klass_or_Instance, inspect.ismethod)

You can read the details here, the explanation about this is under "User-defined methods".

陈独秀 2024-09-16 05:48:12

从对 @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']

From a comment made on @THC4k's answer, it looks like the OP wants to discriminate between built-in methods and methods defined in pure Python code. User defined methods are of types.MethodType, but built-in methods are not.

You can get the various types like so:

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')]

which prints:

['puddle']
['pop', 'popitem']
['pop', 'popitem', 'puddle']
['puddle']
['pop', 'popitem']
['pop', 'popitem', 'puddle']
著墨染雨君画夕 2024-09-16 05:48:12

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

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

我期待有一个更干净的解决方案,但如果没有其他人提出一个解决方案,这可能是您可以使用的东西。我希望我不必使用类的实例来使用 getattribute。

You could use dir to get the name of available methods/attributes/etc, then iterate through them to see which ones are methods. Like this:

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

I'm expecting there to be a cleaner solution, but this could be something you could use if nobody else comes up with one. I'd like if I didn't have to use an instance of the class to use getattribute.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文