来自inspect
模块的classify_class_attrs
函数可用于确定类的每个属性是什么类型的对象,包括函数是实例方法、类方法还是静态方法。举个例子:
from inspect import classify_class_attrs
class Example(object):
@classmethod
def my_class_method(cls):
pass
@staticmethod
def my_static_method():
pass
def my_instance_method(self):
pass
print classify_class_attrs(Example)
这将为Example
上的每个属性输出一个Attribute
对象列表,其中包含关于该属性的元数据。在这种情况下,相关的是:
Attribute(name='my_class_method', kind='class method', defining_class=<class '__main__.Example'>, object=<classmethod object at 0x100535398>)
Attribute(name='my_instance_method', kind='method', defining_class=<class '__main__.Example'>, object=<unbound method Example.my_instance_method>)
Attribute(name='my_static_method', kind='static method', defining_class=<class '__main__.Example'>, object=<staticmethod object at 0x100535558>)
然而,Python的标准库中的许多对象似乎不能以这种方式进行内省。我猜这与许多都是用C实现的事实有关。例如,datetime.datetime.now
用Attribute
对象描述inspect.classify_class_attrs
:
Attribute(name='now', kind='method', defining_class=<type 'datetime.datetime'>, object=<method 'now' of 'datetime.datetime' objects>)
如果我们将其与返回的关于Example
上属性的元数据进行比较,您可能会得出结论datetime.datetime.now
是一个实例方法。但它实际上是一个类方法!你知道吗
from datetime import datetime
print datetime.now() # called from the class: 2014-09-12 16:13:33.890742
print datetime.now().now() # called from a datetime instance: 2014-09-12 16:13:33.891161
有没有可靠的方法来确定stdlib类上的方法是静态方法、类方法还是实例方法?你知道吗
我认为你可以得到很多你想要的东西,区分五种,而不依赖于
inspect
没有记载的任何东西:但使用特定于CPython的实现细节无法区分最后两个。你知道吗
(据我所知,只有3.x在stdlib中有任何内置的静态方法……但当然,即使在2.x中,也有人可以在扩展模块中定义一个静态方法。)
在
inspect
中可用的细节,甚至它的含义在每个版本的Python中都有些不同,部分原因是在2.x和3.x之间发生了变化,部分原因是inspect
基本上是一堆随着时间的推移逐渐改进的启发式算法。你知道吗但至少对于cpython2.6和2.7以及3.3-3.5来说,区分内建实例方法和其他两种类型的最简单方法是^{} 在从类中查找的方法上。对于静态方法或类方法,这将是True;对于实例方法,这将是False。例如:
为什么这样做?嗯,
isbuiltin
会:在实例上查找时,会绑定常规方法或类似
classmethod
的方法。但是在类上查找时,常规方法是未绑定的,而类classmethod
方法是绑定的(类)。当然,类似staticmethod
的方法在任何一种情况下都会变成一个普通的旧函数。所以,这有点间接,但总是正确的。*类方法和静态方法怎么样?你知道吗
在cpython3.x中,内置的静态和类方法描述符在查找它们的类时都返回完全相同的类型,并且没有一个文档化的属性可以用来区分它们。即使这不是真的,我认为引用的编写方式保证了
inspect
中没有函数能够区分它们。你知道吗如果我们转向描述符本身呢?是的,我们有办法区分它们……但我不认为这是语言所能保证的:
为什么这样做?静态方法只是使用一个
staticmethod
描述符,与Python中完全一样(但是包装一个内置函数而不是函数)。但是类和实例方法使用特殊的描述符类型,而不是像Python类和实例方法那样使用classmethod
包装(内置)函数和(内置)函数本身。这些特殊的描述符类型classmethod_descriptor
和method_descriptor
是未绑定的(类和实例)方法,也是绑定它们的描述符。这是真的有历史/实现原因,但我不认为语言引用中有任何东西要求它是真的,甚至没有暗示它。你知道吗如果您愿意依赖实现工件,
isinstance(m, staticmethod)
似乎简单得多尽管如此,除了CPython之外,还有什么实现同时具有内置的staticmethods和classmethods吗?如果不是,记住实用胜过纯洁
*它真正要测试的是该对象是否可以在没有额外参数的情况下调用,但这与文档中的“函数或绑定方法”基本相同;无论哪种方式,它都是您想要的。
相关问题 更多 >
编程相关推荐