首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Python中,实例()可以用来检测类方法吗?

在Python中,实例()可以用来检测类方法吗?
EN

Stack Overflow用户
提问于 2021-12-10 20:54:00
回答 2查看 440关注 0票数 2

如何确定对象是否是类方法?使用实例()不是最好的实践吗?它是如何工作的?

代码语言:javascript
复制
class Foo:
    class_var = 0

    @classmethod
    def bar(cls):
        cls.class_var += 1
        print("class variable value:", cls.class_var)


def wrapper(wrapped: classmethod):
    """
    Call the wrapped method.

    :param wrapped (classmethod, required)
    """
    wrapped()

Foo.bar()
wrapper(Foo.bar)
print("the type is:", type(Foo.bar))
print("instance check success:", isinstance(Foo.bar, classmethod))

输出:

代码语言:javascript
复制
class variable value: 1
class variable value: 2
the type is: <class 'method'>
instance check success: False

Process finished with exit code 0
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-12-10 22:28:29

如果您只想区分常规方法和静态方法之外的类方法,那么您可以使用inspect.ismethod(f)进行检查。

代码语言:javascript
复制
class A:
    def method(self): pass
    @classmethod
    def class_method(cls): pass
    @staticmethod
    def static_method(): pass

在REPL中:

代码语言:javascript
复制
>>> from inspect import ismethod
>>> ismethod(A.method)
False
>>> ismethod(A.class_method)
True
>>> ismethod(A.static_method)
False

如果您更喜欢用isinstance来做这件事,那么使用typing.types.MethodType是可能的

代码语言:javascript
复制
>>> from typing import types
>>> isinstance(A.method, types.MethodType)
False
>>> isinstance(A.class_method, types.MethodType)
True
>>> isinstance(A.static_method, types.MethodType)
False

注意,这些测试将错误地识别(例如,A().method ),因为实际上我们只是在测试绑定方法,而不是非绑定函数。因此,以上解决方案只在以下情况下工作:您正在检查A.something,其中A是类,something是常规方法、类方法或静态方法。

票数 3
EN

Stack Overflow用户

发布于 2021-12-10 21:45:01

如您所知,Python使用对类本身的引用填充classmethod的第一个参数,如果从类或类的实例调用该方法并不重要。方法对象是具有绑定对象的函数。

该对象可以通过.__self__属性检索。因此,您可以简单地检查.__self__属性是否是类。如果它是一个类,那么它就是type类。

一种方法是:

代码语言:javascript
复制
class Foo:

    @classmethod
    def fn1(cls):
        pass

    def fn2(self):
        pass


def is_classmethod(m):
    first_parameter = getattr(m, '__self__', None)
    if not first_parameter:
        return False

    type_ = type(first_parameter)
    return type_ is type


print(is_classmethod(Foo.fn1))
print(is_classmethod(Foo().fn1))
print("-----------------------------------")
print(is_classmethod(Foo.fn2))
print(is_classmethod(Foo().fn2))

产出:

代码语言:javascript
复制
True
True
-----------------------------------
False
False

检查模块中有一个ismethod函数,专门检查对象是否是绑定方法。在检查第一个参数的类型之前,也可以使用它。

注意到:在上面的解决方案中有一个警告,我将在最后提到它。

解决方案2:

您的isinstance解决方案没有工作,因为classmethod是一个描述符。如果您想获得实际的classmethod实例,您应该检查Foo的名称空间并从那里获取方法。

代码语言:javascript
复制
class Foo:

    @classmethod
    def fn1(cls):
        pass

    def fn2(self):
        pass


def is_classmethod(cls, m):
    return isinstance(cls.__dict__[m.__name__], classmethod)


print(is_classmethod(Foo, Foo.fn1))
print(is_classmethod(Foo, Foo().fn1))
print("-----------------------------------")
print(is_classmethod(Foo, Foo.fn2))
print(is_classmethod(Foo, Foo().fn2))

解决方案1警告:例如,如果您有一个简单的MethodType对象,其绑定对象在这里是一个与int不同的类,则此解决方案将无法工作。因为请记住,我们刚刚检查了第一个参数是否为type类型

代码语言:javascript
复制
from types import MethodType

class Foo:
    def fn2(self):
        pass
    fn2 = MethodType(fn2, int)

    @classmethod
    def fn1(cls):
        pass

现在只有2号解决方案起作用了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70310274

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档