python - 为什么在对象未被销毁时调用 python ctypes 类描述符?

标签 python ctypes

>>> from ctypes import *
>>> class A(Structure):
...  _fields_ = [('a', c_int)]
...  def __del__(self):
...   print("destructor called")
... 
>>> a = (A * 10)()
>>> a[0]
<__main__.A object at 0x7f93038cdd08>
>>> a[0]
destructor called
<__main__.A object at 0x7f93038cde18>
>>> a[0]
destructor called
<__main__.A object at 0x7f93038cdd08>
>>> a[0]
destructor called
<__main__.A object at 0x7f93038cde18>

为什么要在这里调用析构函数?为什么每次对象的地址都不一样?为什么 python 不会因双重释放错误而崩溃?

最佳答案

a 是一个代理对象,代表 Python 世界中的 C 结构数组。每次您对该对象进行索引时,ctypes 都会为您创建一个 A 类的新实例,以代理包含的 C 结构。

现在,因为您没有存储对这个新对象的任何引用,所以一旦它的 repr() 值在解释器中被回显,它也会被垃圾收集。

您可以将 a[0] 生成的对象存储在一个新变量中:

>>> foo = a[0]
>>> foo
<__main__.A object at 0x11061ea60>

这个对象将始终与您通过索引 a 的位置 0 创建的任何其他对象不同,但它们都表示相同的 C 结构,因为它们引用相同的地址:

>>> bar = a[0]
>>> foo is bar
False
>>> addressof(foo) == addressof(bar)
True

如果删除此引用,对象将再次被破坏(前提是您当然没有创建对 Python 代理对象的更多引用):

>>> del foo
destructor called

关于python - 为什么在对象未被销毁时调用 python ctypes 类描述符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37051280/

相关文章:

python - 如何从元组列表中删除项目?

python ctype 递归结构

python - 在 Python 中正确丢弃指向 mmap 内存的 ctypes 指针

python - 使用 ctypes 将指针传递给 dll 函数

python - 打包密码软件并分发

python - Jupyter Notebook 中的 Google-oauth

Python ctypes 设置 c_char_p 底层值

python - CPython 中的 id(obj) 和 ctypes.addressof(obj) 有什么区别

python - 如何将默认字符串字符转换为 Python 3.x 中的原始字符?

python - 仅计算regionprops python中的特定属性