[英]In Python can instance() be used to detect a class method?
如何确定 object 是否是 class 方法? 使用 instance() 不是最佳实践吗?如何让它发挥作用?
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))
Output:
class variable value: 1
class variable value: 2
the type is: <class 'method'>
instance check success: False
Process finished with exit code 0
As you know Python fills the first parameter of the classmethod
s with a reference to the class itself and it doesn't matter if you call that method from the class or the instance of the class. 方法 object 是一个 function,它绑定了一个 object。
object 可以通过.__self__
属性检索。 因此,您可以简单地检查.__self__
属性是否为 class 。 如果是 class,则class 是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))
output:
True
True
-----------------------------------
False
False
检查模块中有一个ismethod
专门检查 object 是否是绑定方法。 您也可以在检查第一个参数的类型之前使用它。
您的isinstance
解决方案不起作用,因为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))
如果您只想告诉 class 方法与常规方法和 static 方法不同,那么您可以使用inspect.ismethod(f)
进行检查。
class A:
def method(self): pass
@classmethod
def class_method(self): 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
,因为实际上我们只是在测试绑定方法,而不是未绑定的 function。 因此,上述解决方案仅在您检查A.something
,其中A
是 class 并且something
是常规方法、class 方法或 static 方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.