Python C API — PyDict — нужно ли считать значения и ключи ссылками?

У меня есть код, который использует PyDict для хранения данных. Пользователь устанавливает данные так же, как в обычном словаре Python, и данные сохраняются кодом C в объекте PyDict. Мой вопрос таков: нужно ли мне подсчитывать ссылки (Py_INCREF) на значение И ключ? Только ценность? В документации указано, что вызов PyDict_SetItem НЕ крадет ссылку на значение. Насколько я понимаю, это означает, что объект PyDict не отвечает за значение PyObject, поэтому счетчик ссылок необходимо увеличить. В документах не упоминается ключ - нужно ли его также увеличивать?

Связанный с этим вопрос касается делокатора для моего кода - эти счетчики ссылок необходимо очистить - есть ли какой-либо «краткий путь» для повторения итераций в C API и уменьшения всех ссылок, или мне нужно будет вручную перебирать объект PyDict и уменьшить все значения по отдельности (и, возможно, ключи, в зависимости от ответа на вышеизложенное?)

Рассматриваемый код будет выглядеть примерно так (с вопросами в комментариях):

int myobject_setitem(myobject *self, PyObject *key, PyObject *value) {

    if (value) {
        Py_INCREF(key); // <--- is this needed?
        Py_INCREF(value);
        return PyDict_SetItem(self->data, key, value);
    }
    /* I assume I need to look up the value so I can decrement the reference count
       before removing it from the dictionary, right? */
    PyObject *value = PyDict_GetItem(self->data, key);
    if (!value) {
        return -1;
    }

    int ret = PyDict_DelItem(self->data, key);
    Py_DECREF(key); // <------- is this needed?
    Py_DECREF(value);
    return ret;
}

Что касается деструктора/деаллокатора, я предполагаю, что мне просто нужно выполнить итерацию по dict вручную и уменьшить значения (и, возможно, ключи?), Если нет лучшего способа? (Чтобы было ясно, я имею в виду функцию tp_dealloc)

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
435
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам не нужно выполнять здесь какую-либо обработку счетчика ссылок. Дикту принадлежат все имеющиеся у него ссылки, и он будет управлять вызовами incref/decref. Вы не являетесь владельцем ни одной из создаваемых или уничтожаемых ссылок. Вам также не нужно вызывать PyDict_GetItem.

То же самое касается вашего делокатора. Вы владеете только ссылкой на сам словарь, а не ссылками на его содержимое. Вам нужно только расшифровать dict. Диктатор будет обрабатывать его содержимое.

Значит, я совершенно неправильно понял терминологию? В документах указано, что ссылка не украдена, значит ли это, что новой ссылки нет? Если рассматриваемый объект выходит за пределы области действия вызывающей стороны, он не будет собирать мусор из-под словаря?

Bryant 23.12.2020 02:00

@Bryant: У тебя все наоборот. Если PyDict_SetItem украл ссылки, вам нужно будет выполнить вызовы incref (поскольку вы не владеете ссылками key или value — они заимствованы — поэтому вам нужно будет создать новые ссылки для кражи).

user2357112 23.12.2020 02:05

Вы действительно правы, нужно было более внимательно прочитать документы - спасибо!

Bryant 23.12.2020 02:08

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