Разница между переменными экземпляра и атрибутами в Python? - PullRequest
1 голос
/ 30 июня 2011

Итак, документы Python для расширения письма говорят так:

"Мы хотим выставить наш экземпляр переменные как атрибуты. Есть количество способов сделать это. Самый простой способ - определить члена Определения:

static PyMemberDef Noddy_members[] = {
    {"first", T_OBJECT_EX, offsetof(Noddy, first), 0,
     "first name"},
    {"last", T_OBJECT_EX, offsetof(Noddy, last), 0,
     "last name"},
    {"number", T_INT, offsetof(Noddy, number), 0,
     "noddy number"},
    {NULL}  /* Sentinel */
};

и поместите определения в слот tp_members:

Noddy_members,             /* tp_members */"

Однако мы уже поместили переменные экземпляра в структуру Noddy:

 typedef struct {
    PyObject_HEAD
    PyObject *first;
    PyObject *last;
    int number;
} Noddy;

поэтому мой вопрос в том, почему мы помещаем их в оба места. У меня сложилось впечатление, что это потому, что мы хотим, чтобы и тип, и экземпляр имели их, чтобы мы сохранили значения типов после обновления экземпляра. Но если это так, как значение экземпляра обновляется, если мы меняем атрибут класса? как это:

>>> class foo(object): x = 4
...
>>> f = foo()
>>> f.x
4
>>> foo.x = 5
>>> f.x
5

Ответы [ 2 ]

2 голосов
/ 30 июня 2011

Написание расширения C - сложный процесс, потому что вы должны написать код C и предоставить достаточно информации для Python, чтобы он мог манипулировать вашими данными C, как если бы это были данные Python.Вы должны упомянуть члены структуры дважды: один раз, чтобы компилятор C знал, как создать структуру, а затем снова, чтобы Python знал, где находятся данные и как они называются.

C имеетнет возможности самоанализа, поэтому вы не можете (например) получить список членов структуры во время выполнения.Массив PyMemberDef предоставляет эту информацию.

1 голос
/ 07 июля 2011

Хорошо. Итак, я провел свое исследование, и да, переменные и атрибуты экземпляров различны, и это потому, что экземпляры классов и классы имеют отдельные словари.Как сказано в документации ::

Экземпляр класса создается путем вызова объекта класса (см. Выше).Экземпляр класса имеет пространство имен, реализованное в виде словаря, который является первым местом, в котором ищутся ссылки на атрибуты.Когда атрибут там не найден, а класс экземпляра имеет атрибут с таким именем, поиск продолжается с атрибутами класса.

Таким образом, в основном структура Noddy содержит переменные экземпляра.Noddy_members содержит атрибуты.Кроме того:

Назначения и удаления атрибутов обновляют словарь экземпляра, а не словарь класса.Если в классе есть метод setattr () или delattr (), он вызывается вместо непосредственного обновления словаря экземпляров.

Также:

Если найден атрибут класса, который является объектом пользовательской функции или несвязанным объектом пользовательского метода, связанный класс которого является классом (назовем его C) экземпляра, для которого была инициирована ссылка на атрибутили одна из его баз, она преобразуется в связанный объект пользовательского метода, атрибут im_class которого равен C, а атрибут im_self является экземпляром.Статический метод и объекты метода класса также преобразуются, как если бы они были получены из класса C;см. выше в разделе «Классы».Смотрите раздел Реализация дескрипторов, чтобы узнать, каким образом атрибуты класса, извлекаемые из его экземпляров, могут отличаться от объектов, фактически сохраненных в dict класса.Если атрибут класса не найден, а класс объекта имеет метод getattr (), который вызывается для выполнения поиска.

...