我最近在ctypes中使用了Structure,但我遇到了一个奇怪的问题。
这是我的Python3代码:
from ctypes import *
class AcknowledgeHeader(Structure):
_fields_ = [
('test', c_uint8),
]
ack_header = AcknowledgeHeader()
问题是:test
是AcknowledgeHeader的类成员还是ack_header的实例属性?
我试着找到答案。
如果test
是ack_header的实例属性,那么为什么ack_header.__dict__
会打印一个空字典?
if __name__ == '__main__':
ack_header = AcknowledgeHeader()
print(ack_header.__dict__)
C:\Users\Administrator\PycharmProjects\gige-lib\venv\Scripts\python.exe
C:/Users/Administrator/PycharmProjects/gige-lib/channel/common.py
{}
Process finished with exit code 0
如果test
是AcknowledgeHeader的类成员,那么为什么type(ack_header.test)
不等于type(AcknowledgeHeader.test)
?
if __name__ == '__main__':
ack_header = AcknowledgeHeader()
print(type(ack_header.test))
print(type(AcknowledgeHeader.test))
C:\Users\Administrator\PycharmProjects\gige-lib\venv\Scripts\python.exe C:/Users/Administrator/PycharmProjects/gige-lib/channel/common.py
<class 'int'>
<class '_ctypes.CField'>
Process finished with exit code 0
答案 0 :(得分:4)
test
是AcknowledgeHeader
类上的数据描述符对象。在ack_header
实例上访问它会导致代码在C约定和Python类型之间转换。
因为它是数据描述符,所以捕获与属性的所有交互,包括删除和赋值。如果您要在'test'
属性字典中设置ack_header.__dict__
密钥,则只会被忽略。
相反,ack_header.test
将始终调用AcknowledgeHeader.test.__get__(ack_header, AcknowledgeHeader)
,而ack_header.test
的分配将触发AcknowledgeHeader.test.__set__(ack_header, <new value>)
。
在这种情况下,只实现了获取和设置,没有_ctypes.CField.__delete__()
method,只有__get__
和__set__
,因此del ack_header.test
会抛出异常。
有关描述符如何工作的更多详细信息,请参阅descriptor HOWTO。