类成员或实例属性?

时间:2018-02-28 09:30:42

标签: python python-3.x python-2.7 ctypes

我最近在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

1 个答案:

答案 0 :(得分:4)

testAcknowledgeHeader类上的数据描述符对象。在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