Самоанализ объекта библиотеки Python cffi приводит к изменению объекта __dict__

Я хотел бы получить полный список перечислений из заголовочного файла, используя 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__ не заселено до первого getattr() на класс называется, но реальный вопрос: что делает dir() сделать это заполняет __dict__? призвание hasattr() кажется, делает то же самое.

1 ответ

Решение

Технически причина того, что вы наблюдаете, заключается в том, что dir() пытается получить несколько специальных атрибутов, таких как __members__ на lib объект. Код в cffi лениво добавляет атрибуты по мере их вычисления. Если имя не найдено как функция, он приступает к установке всех объявлений перечислений и пытается вернуть одно из них, если это имя мы пытаемся прочитать. Вот почему попытка прочитать несуществующее имя всегда установит все перечисления в lib.__dict__, (Эта логика только для библиотек, возвращаемых ffi.dlopen(), не для режима API.)

В идеале, вы не должны полагаться ни на что из этого, но в этом случае вы должны: это действительно ошибка. Обратите внимание, что вы можете просто прочитать dir(lib) дважды: во второй раз он будет содержать значения перечисления... (Исправлена ​​ошибка в 19cae8d1a5f6: как минимум dir(lib) должен всегда работать в cffi 1.4--- и больше не перечислять все специальные имена методов Python.)

Другие вопросы по тегам