python cffi 库对象内省导致 __dict__ 对象更改
python cffi library object introspection results in __dict__ object change
我想使用 cffi 从头文件中获取枚举的完整列表。但是我看到了一个奇怪的行为:通过观察对象,我迫使底层 __dict__
发生变化:
>>> from cffi import FFI
>>> ffi = FFI()
>>> ffi.cdef('typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;')
>>> c = ffi.dlopen('c')
# the dictionary is empty
>>> print c.__dict__
{}
>>> dir(c)
# the dictionary is populated
>>> print c.__dict__
{'SEARCH': 2, 'RANDOM': 0, 'IMMEDIATE': 1}
我猜 __dict__
直到 class 上的第一个 getattr()
被调用后才会被填充,但真正的问题是:dir()
做了什么填充 __dict__
?调用 hasattr()
似乎做同样的事情。
从技术上讲,您观察到的原因是 dir()
试图在 lib
对象上获取一些特殊属性,例如 __members__
。 cffi 中的代码在计算属性时延迟添加属性。如果找不到作为函数的名称,它会继续安装所有枚举声明并尝试 return 其中之一(如果这是我们尝试读取的名称)。这就是为什么尝试读取一个不存在的名称总是会在 lib.__dict__
中安装所有枚举。 (此逻辑仅适用于由 ffi.dlopen()
编辑的库 return,不适用于 API 模式。)
理想情况下,您不应该依赖其中的任何一个,但在这种情况下您必须:这确实是一个错误。请注意,您可以简单地读取 dir(lib)
两次:第二次,它将包含枚举值...
(修复了 19cae8d1a5f6 中的错误:至少 dir(lib)
应该始终在 cffi 1.4 中工作---并且不再列出所有特殊的 Python 方法名称。)
我想使用 cffi 从头文件中获取枚举的完整列表。但是我看到了一个奇怪的行为:通过观察对象,我迫使底层 __dict__
发生变化:
>>> from cffi import FFI
>>> ffi = FFI()
>>> ffi.cdef('typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;')
>>> c = ffi.dlopen('c')
# the dictionary is empty
>>> print c.__dict__
{}
>>> dir(c)
# the dictionary is populated
>>> print c.__dict__
{'SEARCH': 2, 'RANDOM': 0, 'IMMEDIATE': 1}
我猜 __dict__
直到 class 上的第一个 getattr()
被调用后才会被填充,但真正的问题是:dir()
做了什么填充 __dict__
?调用 hasattr()
似乎做同样的事情。
从技术上讲,您观察到的原因是 dir()
试图在 lib
对象上获取一些特殊属性,例如 __members__
。 cffi 中的代码在计算属性时延迟添加属性。如果找不到作为函数的名称,它会继续安装所有枚举声明并尝试 return 其中之一(如果这是我们尝试读取的名称)。这就是为什么尝试读取一个不存在的名称总是会在 lib.__dict__
中安装所有枚举。 (此逻辑仅适用于由 ffi.dlopen()
编辑的库 return,不适用于 API 模式。)
理想情况下,您不应该依赖其中的任何一个,但在这种情况下您必须:这确实是一个错误。请注意,您可以简单地读取 dir(lib)
两次:第二次,它将包含枚举值...
(修复了 19cae8d1a5f6 中的错误:至少 dir(lib)
应该始终在 cffi 1.4 中工作---并且不再列出所有特殊的 Python 方法名称。)