如何确定对象是否是类方法?使用实例()不是最好的实践吗?它是如何工作的?
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))输出:
class variable value: 1
class variable value: 2
the type is: <class 'method'>
instance check success: False
Process finished with exit code 0发布于 2021-12-10 22:28:29
如果您只想区分常规方法和静态方法之外的类方法,那么您可以使用inspect.ismethod(f)进行检查。
class A:
def method(self): pass
@classmethod
def class_method(cls): pass
@staticmethod
def static_method(): pass在REPL中:
>>> from inspect import ismethod
>>> ismethod(A.method)
False
>>> ismethod(A.class_method)
True
>>> ismethod(A.static_method)
False如果您更喜欢用isinstance来做这件事,那么使用typing.types.MethodType是可能的
>>> 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是常规方法、类方法或静态方法。
发布于 2021-12-10 21:45:01
如您所知,Python使用对类本身的引用填充classmethod的第一个参数,如果从类或类的实例调用该方法并不重要。方法对象是具有绑定对象的函数。
该对象可以通过.__self__属性检索。因此,您可以简单地检查.__self__属性是否是类。如果它是一个类,那么它就是type类。
一种方法是:
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))产出:
True
True
-----------------------------------
False
False检查模块中有一个ismethod函数,专门检查对象是否是绑定方法。在检查第一个参数的类型之前,也可以使用它。
注意到:在上面的解决方案中有一个警告,我将在最后提到它。
解决方案2:
您的isinstance解决方案没有工作,因为classmethod是一个描述符。如果您想获得实际的classmethod实例,您应该检查Foo的名称空间并从那里获取方法。
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类型
from types import MethodType
class Foo:
def fn2(self):
pass
fn2 = MethodType(fn2, int)
@classmethod
def fn1(cls):
pass现在只有2号解决方案起作用了。
https://stackoverflow.com/questions/70310274
复制相似问题