Рубрики
Без рубрики

Настройте свой собственный словарь – Советы Python

TL; Коллекции DR подкласс. Userdict, не определяется. Дольше описание мне нужен дик … Теги с Python.

TL; доктор

Подкласс коллекции. Userdict , не Дикт Отказ

Дольше описание

Мне нужна словарь, подобная переменную, и пропустите ее к другой функции, когда функция возвращается, мне нужно знать, был ли этот словарь изменен (ключ или значение), если оно есть, я сделаю сохранение базы данных (если Видя это как процесс спасения сеансов на стороне сервера, это именно). Поскольку это частое операция, я хочу сделать это как можно быстрее.

Первая идея пришла на мой взгляд, как это:

session_dict = {}
old_dict = {**session_dict}
# now call function
func(session_dict)
if session_dict != old_dict:
    # change happend, do database saving

Но этот метод требует копии словаря, которая стоила больше места и сравнивайте два объекта словаря, я уверен, что внутри появилось некоторое рекурсивное сравнение, которое может стоить больше времени.

Вторая идея использует Парил Для сравнения маринованной строки:

import pickle
session_dict = {}
finger_print = pickle.dumps(session_dict)
func(session_dict)
if pickle.dumps(session_dict) == finger_print:
    # change happend, do database saving

Это использует Pickle.dumps Чтобы преобразовать словарь в строку, затем после вызова функции он сравнивает строку. На основании того, как долго строка, это может стоить больше времени процессора.

Третья идея – подкласс Дикт , а когда __setitem__ и __delitem__ называются, отметьте флаг изменения (вы также можете увидеть мой предыдущий пост здесь на подклассном дикторе В Python для поддержки доступа точечного синтаксиса):

class ChangeDetectableDict(dict):
    def __init__(self, val=None):
        if val is None:
            val = {}
        super().__init__(val)
        self.changed = False

    def __setitem__(self, item, value):
        super().__setitem__(item, value)
        self.changed = True

    def __delitem__(self, item):
        super().__delitem__(item)
        self.changed = True

Это отлично работает, если у нас есть код, чтобы установить ключ:

session_dict = ChangeDetectableDict()
session_dict["name"] = "bo"
print(session_dict.changed) # True

Или удалить ключ:

session_dict = ChangeDetectableDict({"name": "bo"})
del session_dict["name"]
print(session_dict.changed) # True

Это сделает обнаружение изменений во времени O (1) , что отлично. Но вы можете увидеть проблему, что если я установлю значение ключа, чтобы быть одинаковым значением, изменился все еще будет помечено как True:

session_dict = ChangeDetectableDict({"name": "bo"})
session_dict["name"] = "bo"]
print(session_dict.changed) # True

В моем случае я в порядке с этим, пока что-то изменилось, изменился Будет отмечен как True, я не против, чтобы иметь несколько ложных положительных случаев. Но настоящая проблема в том, что если я не пользуюсь дель Чтобы удалить ключ, использовать поп вместо этого __delitem__ Метод не будет вызван, таким образом изменился все еще ложно:

session_dict = ChangeDetectableDict({"name": "bo"})
session_dict.pop("name", None)
print(session_dict.changed) # False

Это недопустимо для моего случая использования, и причина, по которой это происходит, это потому, что встроенный Python Дикт имеет некоторые встроенные оптимизации, которые ведут поп не звонить __delitem__ Отказ

Итак, четвертый метод, который я нашел, не подклассно обдумывать вместо этого подкласс коллекции. Userdict :

from collections import UserDict

class ChangeDetectableDict(UserDict):
    def __init__(self, val=None):
        if val is None:
            val = {}
        super().__init__(val)
        self.changed = False

    def __setitem__(self, item, value):
        super().__setitem__(item, value)
        self.changed = True

    def __delitem__(self, item):
        super().__delitem__(item)
        self.changed = True

Теперь независимо от того, мы не используем дель или поп , __delitem__ Метод всегда будет вызывать Таким образом, отметьте изменился быть правдой.

Вернуться к началу, теперь я могу написать код так:

session_dict = ChangeDetectableDict()
func(session_dict)
if session_dict.changed:
    # change happend, do database saving

Оригинал: “https://dev.to/0xbf/customize-your-own-dictionary-python-tips-5b47”