无法将属性添加到 ctypes 中的嵌套结构
Unable to add attribute to a nested structure in ctypes
我试图向嵌套的 ctypes 结构添加一些诊断,但没有成功,我想知道原因。按预期工作的简单示例:
import ctypes
class FirstStruct(ctypes.Structure):
_fields_ = [('ch', ctypes.c_ubyte)]
f = FirstStruct()
print type(f)
print hasattr(f, 'helper')
f.helper = 'xyz'
print hasattr(f, 'helper')
这些行打印出了我的预期:
<class '__main__.FirstStruct'>
False
True
但是当我在另一个结构中使用它时它失败了:
class SecondStruct(ctypes.Structure):
_fields_ = [('first', FirstStruct)]
s = SecondStruct()
print type(s.first)
print hasattr(s.first, 'helper')
s.first.helper = 'xyz'
print hasattr(s.first, 'helper')
以上结果
<class '__main__.FirstStruct'>
False
False
有人可以解释一下区别吗?
(我在 Python 2.7.8 上 运行 它。请注意,我不想更改结构本身,但想在 ctypes 结构之外添加一个额外的变量。)
编辑:
这里有一个更直接的例子:
import ctypes
class FirstStruct(ctypes.Structure):
_fields_ = [('ch', ctypes.c_ubyte)]
class SecondStruct(ctypes.Structure):
_fields_ = [('first', FirstStruct)]
f = FirstStruct()
s = SecondStruct()
f.helper = 'aaa'
s.first.helper = 'bbb'
s.first.ch = 0
t = s.first
t.helper = 'ccc'
t.ch = 12
print f.helper # aaa
print t.ch # 12
print s.first.ch # 12
print t.helper # ccc
print s.first.helper # AttributeError: 'FirstStruct' object has no attribute 'helper'
问题是:为什么 s.first
和 t
不等价,为什么 s.first.helper
不触发警告,如果我毕竟无法设置它?
如果您使用复制模块,您可以获得您创建的ctype 对象的当前快照。所以尝试:
import copy
import ctypes
class FirstStruct(ctypes.Structure):
_fields_ = [('ch', ctypes.c_ubyte)]
f = FirstStruct()
print type(f)
print hasattr(f, 'helper')
f.helper = 'xyz'
print hasattr(f, 'helper')
t = copy.copy(f)
print hasattr(t, 'helper')
>>> True
在您的第二个示例中,s.first
返回内部结构的副本。您可以通过查看其 id()
:
来了解这一点
>>> id(s.first)
112955080L
>>> id(s.first) # didn't change
112955080L
>>> f=s.first # capture a reference the object returned
>>> id(f) # still the same
112955080L
>>> id(s.first) # changed!
113484232L
发生的事情是返回的新副本一直被分配到相同的地址,但立即被释放。引用后,副本在另一个地址。
所以你正在创建一个helper
属性,只是在一个临时对象上。
在您的第一个示例中,f
直接引用 FirstStruct
实例,因此您可以设置和读取属性。
我试图向嵌套的 ctypes 结构添加一些诊断,但没有成功,我想知道原因。按预期工作的简单示例:
import ctypes
class FirstStruct(ctypes.Structure):
_fields_ = [('ch', ctypes.c_ubyte)]
f = FirstStruct()
print type(f)
print hasattr(f, 'helper')
f.helper = 'xyz'
print hasattr(f, 'helper')
这些行打印出了我的预期:
<class '__main__.FirstStruct'>
False
True
但是当我在另一个结构中使用它时它失败了:
class SecondStruct(ctypes.Structure):
_fields_ = [('first', FirstStruct)]
s = SecondStruct()
print type(s.first)
print hasattr(s.first, 'helper')
s.first.helper = 'xyz'
print hasattr(s.first, 'helper')
以上结果
<class '__main__.FirstStruct'>
False
False
有人可以解释一下区别吗? (我在 Python 2.7.8 上 运行 它。请注意,我不想更改结构本身,但想在 ctypes 结构之外添加一个额外的变量。)
编辑:
这里有一个更直接的例子:
import ctypes
class FirstStruct(ctypes.Structure):
_fields_ = [('ch', ctypes.c_ubyte)]
class SecondStruct(ctypes.Structure):
_fields_ = [('first', FirstStruct)]
f = FirstStruct()
s = SecondStruct()
f.helper = 'aaa'
s.first.helper = 'bbb'
s.first.ch = 0
t = s.first
t.helper = 'ccc'
t.ch = 12
print f.helper # aaa
print t.ch # 12
print s.first.ch # 12
print t.helper # ccc
print s.first.helper # AttributeError: 'FirstStruct' object has no attribute 'helper'
问题是:为什么 s.first
和 t
不等价,为什么 s.first.helper
不触发警告,如果我毕竟无法设置它?
如果您使用复制模块,您可以获得您创建的ctype 对象的当前快照。所以尝试:
import copy
import ctypes
class FirstStruct(ctypes.Structure):
_fields_ = [('ch', ctypes.c_ubyte)]
f = FirstStruct()
print type(f)
print hasattr(f, 'helper')
f.helper = 'xyz'
print hasattr(f, 'helper')
t = copy.copy(f)
print hasattr(t, 'helper')
>>> True
在您的第二个示例中,s.first
返回内部结构的副本。您可以通过查看其 id()
:
>>> id(s.first)
112955080L
>>> id(s.first) # didn't change
112955080L
>>> f=s.first # capture a reference the object returned
>>> id(f) # still the same
112955080L
>>> id(s.first) # changed!
113484232L
发生的事情是返回的新副本一直被分配到相同的地址,但立即被释放。引用后,副本在另一个地址。
所以你正在创建一个helper
属性,只是在一个临时对象上。
在您的第一个示例中,f
直接引用 FirstStruct
实例,因此您可以设置和读取属性。