gpt4 book ai didi

python - 如何为通过 ctypes _fields_ 创建的(可能是多维的)数组重写 __setitem__ 方法?

转载 作者:太空宇宙 更新时间:2023-11-03 19:17:56 24 4
gpt4 key购买 nike

我正在Python 3.2.2中使用ctypes来封装一些C数据结构。最终目标是能够拥有一个包装 C 结构的对象,当该结构的数据被通知时内容已修改。

代表代码:

from ctypes import *

class Comm(Structure):
def __init__(self):
self.attributes_updated = False

def __setattr__(self, name, value):
super(Comm, self).__setattr__('attributes_updated', True)
super(Comm, self).__setattr__(name, value)


class MyCStruct(Comm):
_fields_ = [('number', c_int),
('array', c_int*5)]

def __init__(self):
Comm.__init__(self)

这对于任何简单的数据属性(例如“数字”)都非常有用。

>>> s = MyCStruct()
>>> s.attributes_updated
False
>>> s.value = 123
>>> s.attributes_updated
True

由于 __setattr__ 不会被调用以通过索引表示法访问array 属性,因此我想重写 C 结构体中数组成员的 __setitem__ 属性。据推测,那时我需要包含对包含对象的引用,以便可以更改包含对象的 attributes_updated 变量,但我还没有达到能够捕获的程度以方便的方式访问数组属性,我可以捕获对简单属性的访问。有没有办法在 ctypes 通过 _fields_ 变量创建的可索引对象上执行此操作?是否可以覆盖 s.array 上的 __setitem__ ?可能有更好的方法来做到这一点吗?

理想情况下,会发生这种情况:

>>> s = MyCStruct()
>>> s.attributes_updated
False
>>> s.array[2] = 456
>>> s.attributes_updated
True

编辑后续问题:

多维数组怎么样?

class MyCStruct(Comm):
_fields_ = [('number', c_int),
('array', (c_int*5)*2]

我错误地期望了下面的答案,它对于单维数组非常有效,可以对任意嵌套的数组执行相同的操作。应该有一种方法可以递归地生成代理对象,以便对多维数组执行相同的操作,是吗?我忽略了语法。

最佳答案

我认为一个不错的解决方案是返回一个代理对象而不是数组,然后它可以处理对数组的访问。可能是这样的:

from ctypes import *

class ArrayProxy(object):
def __init__(self, array, struct):
self.array = array
self.struct = struct

def __setitem__(self, i, val):
self.array[i] = val
self.struct.attributes_updated = True

def __getitem__(self, i):
item = self.array[i]
if issubclass(type(item), Array):
# handle multidimensional arrays
return ArrayProxy(item, self.struct)
return item

class Comm(Structure):
def __init__(self):
self.attributes_updated = False

def __setattr__(self, name, value):
super(Comm, self).__setattr__('attributes_updated', True)
super(Comm, self).__setattr__(name, value)

def __getattribute__(self, name):
attr = super(Comm, self).__getattribute__(name)
if issubclass(type(attr), Array):
return ArrayProxy(attr, self)
return attr


class MyCStruct(Comm):
_fields_ = [('number', c_int),
('array', c_int*5),
('multiarray', c_int*2*1),]

def __init__(self):
Comm.__init__(self)

s = MyCStruct()
print s.array
# <__main__.ArrayProxy object at 0x1b1f3d0>
print s.attributes_updated
# False
s.array[0] = 1
print s.attributes_updated
# True

s2 = MyCStruct()
s2.multiarray[0][0] = 1
print s2.attributes_updated
# True

关于python - 如何为通过 ctypes _fields_ 创建的(可能是多维的)数组重写 __setitem__ 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10727080/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com