我正在尝试使用h5py模块将一组深度嵌套的类,属性,绑定方法等编写到HDF5文件中以进行长期存储.我真的很亲密 我似乎无法解决的唯一问题是以编程方式在运行时找出一种方法来确定某些东西是否是类实例类型,而不是列表,int等.我需要递归到类实例,但显然不应该递归到int,float等.这需要适用于旧式和新式类.我研究过的东西不起作用/我无法开始工作:
使用检查模块
>>> class R(object): pass
...
>>> _R = R()
>>> import inspect
>>> inspect.isclass(_R)
False
>>> inspect.isclass(R)
True
Run Code Online (Sandbox Code Playgroud)
这没用,我需要一个像inspect.isclassinstance(_R)返回的函数True
使用类型模块
如果使用旧式类,则会有一个名为InstanceType的类型,它匹配旧式类的实例,如下面的代码所示
>>> import types
>>> class R(): pass #old-style class
...
>>> _R = R()
>>> import types
>>> type(_R) is types.InstanceType
True
>>> class R(object): pass #new-style class
...
>>> _R = R()
>>> type(_R) is types.InstanceType
False
Run Code Online (Sandbox Code Playgroud)
但是如果使用新式类,则没有相应的类型 types
虽然海报很可能需要重新考虑他的设计,但在某些情况下,有合理的需要区分在C中创建的内置/扩展类型的实例和在Python中使用该class语句创建的类的实例.虽然两者都是类型,但后者是CPython内部称为"堆类型"的类型,因为它们的类型结构是在运行时分配的.可以在__repr__输出中看到python继续区分它们:
>>> int # "type"
<type 'int'>
>>> class X(object): pass
...
>>> X # "class"
<class '__main__.X'>
Run Code Online (Sandbox Code Playgroud)
该__repr__区别正是通过检查类型是否是一个堆型实现.
根据应用程序的确切需要,is_class_instance可以通过以下方式之一实现功能:
# Built-in types such as int or object do not have __dict__ by
# default. __dict__ is normally obtained by inheriting from a
# dictless type using the class statement. Checking for the
# existence of __dict__ is an indication of a class instance.
#
# Caveat: a built-in or extension type can still request instance
# dicts using tp_dictoffset, and a class can suppress it with
# __slots__.
def is_class_instance(o):
return hasattr(o, '__dict__')
# A reliable approach, but one that is also more dependent
# on the CPython implementation.
Py_TPFLAGS_HEAPTYPE = (1<<9) # Include/object.h
def is_class_instance(o):
return bool(type(o).__flags__ & Py_TPFLAGS_HEAPTYPE)
Run Code Online (Sandbox Code Playgroud)
编辑
以下是该函数的第二个版本的说明.它确实使用CPython内部用于其自身目的的相同测试来测试该类型是否为"堆类型".这确保了对于堆类型("类")的实例它将始终返回True,对于非堆类型的实例("类型",以及旧样式类,这很容易修复)将始终返回False.它通过检查C级结构的tp_flags成员是否设置了位来实现.实现的薄弱部分是它将常量的值硬编码到当前观察到的值.(这是必要的,因为常量不会通过符号名称暴露给Python.)虽然理论上这个常量可能会改变,但实际上很可能不会发生,因为这样的改变会无意中破坏现有扩展模块的ABI.看一下常量的定义,很明显,在不打扰旧的常量的情况下,新的常量被加入.另一个缺点是,这个代码在非CPython实现上运行的可能性为零,例如Jython或IronPython.PyTypeObjectPy_TPFLAGS_HEAPTYPEPy_TPFLAGS_HEAPTYPEPy_TPFLAGSInclude/object.h
| 归档时间: |
|
| 查看次数: |
921 次 |
| 最近记录: |