2

Is there a better way to initialize a ctypes field that is meant to be static/constant than what I have below?

from ctypes import *

class foo(LittleEndianStructure):
  _fields_ = [
    ("signature", c_ulonglong),
    ]

  def __init__(self):
      super(LittleEndianStructure,self).__init__()
      self.signature = 0x896489648964

f = foo()
print hex(f.signature)

For example, I was hoping I could do something similar to how you could do it with a normal python object:

class bar:
    signature = 0x896489648964

b = bar()
print hex(b.signature)
4

1 回答 1

2

简短的回答是否定的,你不能这样做,也不应该这样做。


您的普通 Python 对象示例不会按照您的想法进行。它不会自动初始化实例属性;它正在创建一个类属性。

在某些情况下,它们的工作方式相似,但它们不是一回事。例如,比较:

>>> class Foo(object):
...     bar=[]
...     def __init__(self):
...         self.baz=[]
... 
>>> f1 = Foo()
>>> f2 = Foo()
>>> f1.bar.append(100)
>>> f1.baz.append(100)
>>> f2.bar
[100]
>>> f2.baz
[]

在这里,f1每个实例f2都初始化了自己的baz,但它们不会自动初始化自己的—— 它们与其他实例bar共享一个。bar

而且,与本案更直接相关:

>>> f1.__dict__
{'baz': [1]}

barclass 属性不是f1's 字典的一部分。

因此,将相同的内容翻译成,如果您将其设为类属性ctypes,您"signature"将不会成为结构的成员——也就是说,它不会作为每个实例的一部分布置在内存中。这将破坏拥有它的全部目的。


如果您了解 C++,那么用 C++ 术语来看待它可能会有所帮助。

像上面一样,类属性bar有点像 C++ 中的静态成员变量,而实例属性就像普通的实例成员变量。

在此 C++ 代码中:

struct bar {
    static const long signature = 0x896489648964;
};

……每个bar实际上都是一个空结构;有一个bar::signature存储在内存中的其他地方。您可以通过bar实例引用它,但这只是因为编译器变成b1.signaturebar::signature.


* 我说“有点”的原因是 Python 类属性可以被子类覆盖,而 C++ 静态成员不能,它们实际上只是全局变量,它们只能被子类“隐藏”。

于 2013-07-11T19:30:44.933 回答