我有一个类,它具有其他类的实例作为其属性:
from ctypes import *
class C():
A = propA()
B = propB()
def __init__(self):
class c_struct(Structure):
_fields_ = [('_A', c_int), ('_B', c_int)]
self._c_struct = c_struct()
我需要以某种方式将 propA
和 propB
类“连接”到用 C
创建的内部结构 _c_struct
> 最终得到这样的行为:
c = C()
c.A.val = 12
c.B.val = 13
c._c_struct._A == c.A.val == 12
其中C.A
能够操作C._c_struct._A
。我尝试过做这样的事情:
from ctypes import *
class propParent():
def set_ref(self, ext_ref):
self._val = ext_ref
@property
def val(self):
return self._val
@val.setter
def val(self, val):
self._val = val
class propA(propParent):
# Further definitions here
pass
class propB(propParent):
# Further definitions here
pass
class C():
A = propA()
B = propB()
def __init__(self):
class c_struct(Structure):
_fields_ = [('_A', c_int), ('_B', c_int)]
self._c_struct = c_struct()
self.A.set_ref(self._c_struct._A)
self.B.set_ref(self._c_struct._B)
但似乎 self._c_struct._A
返回一个 Python 整数对象,而不是对该结构的 _A
内部 c_int 对象的引用。如何将一个属性连接到同一类中另一个属性的子属性?
这似乎适合 descriptor ,其中 field c_struct._A
is also :
In [3]: c_struct._A
Out[3]: <Field type=c_int, ofs=0, size=4>
In [4]: c_struct._A.__get__
Out[4]: <method-wrapper '__get__' of _ctypes.CField object at 0x7f967303cf48>
这就是为什么当通过 c_struct
实例而不是字段本身访问时它返回一个 int
。首先定义一个适合您的用例的方法:
class prop:
def __init__(self, name):
self.name = name
def __repr__(self):
return 'prop({!r})'.format(self.name)
def __get__(self, instance, owner):
if not instance:
return self
return getattr(instance._c_struct, '_{}'.format(self.name))
def __set__(self, instance, value):
setattr(instance._c_struct, '_{}'.format(self.name), value)
或者只是
def prop(name):
name = '_{}'.format(name)
return property(
lambda self: getattr(self._c_struct, name),
lambda self, value: setattr(self._c_struct, name, value))
然后定义你的原始类:
class C:
A = prop('A')
B = prop('B')
def __init__(self):
class c_struct(Structure):
_fields_ = [('_A', c_int), ('_B', c_int)]
self._c_struct = c_struct()
测试:
In [36]: c = C()
In [37]: c.A
Out[37]: 0
In [38]: c._c_struct._A
Out[38]: 0
In [39]: c.A = 12
In [40]: c._c_struct._A
Out[40]: 12
为了获得额外的积分,如果您使用的是足够新的 Python 版本,您可以使用 object.__set_name__()
消除重复名称的需要,而不必求助于元类:
class prop:
def __init__(self, name=None):
self.name = name
def __set_name__(self, owner, name):
if self.name is None:
self.name = name
...
然后将 C 定义为:
class C:
A = prop()
B = prop()
...
我是一名优秀的程序员,十分优秀!