假设以下类定义:
class A:
def f(self):
return 'this is f'
@staticmethod
def g():
return 'this is g'
a = A()
因此f是常规方法,g是静态方法。
现在,如何检查功能对象a.f和a.g是否为静态? Python中有“isstatic”功能吗?
我必须知道这一点,因为我有包含许多不同函数(方法)对象的列表,并且要调用它们我必须知道它们是否期望“自我”作为参数。
答案 0 :(得分:14)
让我们试一下:
>>> import types
>>> class A:
... def f(self):
... return 'this is f'
... @staticmethod
... def g():
... return 'this is g'
...
>>> a = A()
>>> a.f
<bound method A.f of <__main__.A instance at 0x800f21320>>
>>> a.g
<function g at 0x800eb28c0>
>>> isinstance(a.g, types.FunctionType)
True
>>> isinstance(a.f, types.FunctionType)
False
因此看起来您可以使用types.FunctionType
来区分静态方法。
答案 1 :(得分:12)
您的方法对我来说似乎有点不妥,但您可以检查类属性:
(在Python 2.7中):
>>> type(A.f)
<type 'instancemethod'>
>>> type(A.g)
<type 'function'>
或Python 3.x中的实例属性
>>> a = A()
>>> type(a.f)
<type 'method'>
>>> type(a.g)
<type 'function'>
答案 2 :(得分:3)
为什么要这么麻烦?你可以打电话给你,就像你打电话给f:
a = A()
a.f()
a.g()
答案 3 :(得分:2)
我碰巧有一个模块来解决这个问题。它是兼容Python2 / 3的解决方案。并且允许使用方法从父类继承进行测试。
另外,这个模块还可以测试:
例如:
class Base(object):
attribute = "attribute"
@property
def property_method(self):
return "property_method"
def regular_method(self):
return "regular_method"
@staticmethod
def static_method():
return "static_method"
@classmethod
def class_method(cls):
return "class_method"
class MyClass(Base):
pass
以下是 staticmethod 的解决方案。但是我建议使用模块 posted here。
import inspect
def is_static_method(klass, attr, value=None):
"""Test if a value of a class is static method.
example::
class MyClass(object):
@staticmethod
def method():
...
:param klass: the class
:param attr: attribute name
:param value: attribute value
"""
if value is None:
value = getattr(klass, attr)
assert getattr(klass, attr) == value
for cls in inspect.getmro(klass):
if inspect.isroutine(value):
if attr in cls.__dict__:
bound_value = cls.__dict__[attr]
if isinstance(bound_value, staticmethod):
return True
return False
答案 4 :(得分:1)
在这里补充答案,在Python 3中,最好的方法如下:
import inspect
class Test:
@staticmethod
def test(): pass
isstatic = isinstance(inspect.getattr_static(Test, "test"), staticmethod)
我们使用getattr_static
而不是getattr
,因为getattr
将检索绑定的方法或函数,而不是staticmethod
类对象。您可以对classmethod
类型和property
的类型进行类似的检查(例如,使用@property
装饰器定义的属性)
请注意,即使它是staticmethod
,也不要假定它是在类内部定义的。方法源可能源自另一个类。要获取真实的源代码,可以查看基础函数的合格名称和模块。例如:
class A:
@staticmethod:
def test(): pass
class B: pass
B.test = inspect.getattr_static(A, "test")
print("true source: ", B.test.__qualname__)
从技术上讲,任何方法都可以用作“静态”方法,只要在类本身上调用它们即可,因此请记住这一点。例如,这将很好地工作:
class Test:
def test():
print("works!")
Test.test()
该示例不适用于Test
的 instances ,因为该方法将绑定到实例并被称为Test.test(self)
。
实例和类方法在某些情况下也可以用作静态方法,只要正确处理第一个arg。
class Test:
def test(self):
print("works!")
Test.test(None)
也许另一个罕见的情况是staticmethod
也绑定到类或实例。例如:
class Test:
@classmethod
def test(cls): pass
Test.static_test = staticmethod(Test.test)
尽管从技术上讲它是staticmethod
,但实际上它的行为类似于classmethod
。因此,在自省时,您可以考虑检查__self__
(在__func__
上进行递归检查)以查看该方法是否绑定到类或实例。