带有ctypes属性的Python类有副作用

时间:2017-12-14 15:22:54

标签: python python-3.x ctypes mutable

我为图像缓冲区创建了一个类。该课程如下:

import ctypes

class ImgBuf():
    def __init__(self, bufnr=ctypes.c_int(-1)):
        self.bufnr = bufnr

属性'bufnr'通过引用移交给共享库,并更改为缓冲区管理。我想拥有这个类的多个实例(管理多个图像缓冲区)。在小例子中

import imgBuf.ImgBuf
buf1 = dicamsdk.ImgBuf()
buf2 = dicamsdk.ImgBuf()
sharedDLL.allocateBuffer(buf1)

两个实例中的bufNr都已更改。如何使实例独立?

3 个答案:

答案 0 :(得分:2)

ctypes.c_intlist一样,是可变的,不应该用作默认参数,这是一个非常常见的错误。每次调用函数时都应该创建一个新对象:

class ImgBuf():
    def __init__(self, bufnr=None):
        if bufnr is None:
            bufnr = ctypes.c_int(-1)
        self.bufnr =ctypes.c_int(bufnr)

答案 1 :(得分:1)

bufnr之类的kwargs的默认值只会在读取def语句时在加载时评估一次。因此,在这种情况下,c_int将创建一次,然后相同的实例将用于所有未明确指定ImgBuf的{​​{1}}个实例。

为避免这种情况,您可以使用bufnr作为默认值,然后检查None并在函数体内需要时实例化默认值,每次创建一个新实例时间。

这同样适用于用作默认值的任何其他可变对象,如列表,dicts等。请参阅this link

答案 2 :(得分:-1)

请参阅以下代码剪辑:

from imgBuf import ImgBuf
buf1 = ImgBuf()
buf2 = ImgBuf()
print('id(buf1) == id(buf2): ', id(buf1) == id(buf2))
print('id(buf1.bufnr) == id(buf2.bufnr): ', id(buf1.bufnr) == id(buf2.bufnr))

输出

id(buf1) == id(buf2):  False
id(buf1.bufnr) == id(buf2.bufnr):  True

即使python正确创建了类对象的两个实例,ctypes值也具有相同的标识。通常,这不是问题,因为python管理存储。但这不适用于正在使用的共享库。

已复制默认值以确保独立实例。该课程如下:

import ctypes
from copy import copy

class ImgBuf():
    def __init__(self, bufnr=ctypes.c_int(-1)):
        self.bufnr = copy(ctypes.c_int(bufnr))

现在对象应该是独立的(再次运行代码剪切)。