Как мне запомнить экземпляр класса в Python?

Хорошо, вот сценарий реального мира: я пишу приложение, и у меня есть класс, который представляет определенный тип файлов (в моем случае это фотографии, но эта деталь не имеет отношения к проблеме). Каждый экземпляр класса Photograph должен быть уникальным для имени файла фотографии.

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

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

В моем исследовании я нашел Python__new__() метод, и я действительно смог написать рабочий тривиальный пример, но он развалился, когда я попытался использовать его на своих объектах реального мира, и я не уверен почему (единственное, что я могу думать, это то, что мой реальный объекты мира были подклассами других объектов, которые я не могу реально контролировать, и поэтому при таком подходе были некоторые несовместимости). Вот что у меня было:

class Flub(object):
    instances = {}

    def __new__(cls, flubid):
        try:
            self = Flub.instances[flubid]
        except KeyError:
            self = Flub.instances[flubid] = super(Flub, cls).__new__(cls)
            print 'making a new one!'
            self.flubid = flubid
        print id(self)
        return self

    @staticmethod
    def destroy_all():
        for flub in Flub.instances.values():
            print 'killing', flub


a = Flub('foo')
b = Flub('foo')
c = Flub('bar')

print a
print b
print c
print a is b, b is c

Flub.destroy_all()

Какой вывод это:

making a new one!
139958663753808
139958663753808
making a new one!
139958663753872
<__main__.Flub object at 0x7f4aaa6fb050>
<__main__.Flub object at 0x7f4aaa6fb050>
<__main__.Flub object at 0x7f4aaa6fb090>
True False
killing <__main__.Flub object at 0x7f4aaa6fb050>
killing <__main__.Flub object at 0x7f4aaa6fb090>

Это прекрасно! Только два экземпляра были сделаны для двух уникальных идентификаторов, а в Flub.instances явно есть только два перечисленных.

Но когда я попытался использовать этот подход с объектами, которые я использовал, я получил всевозможные бессмысленные ошибки о том, как__init__() взял только 0 аргументов, а не 2. Так что я бы изменил некоторые вещи, и тогда он сказал бы мне, что__init__() нужен аргумент. Совершенно странно.

После некоторого времени борьбы с ним, я просто сдался и переместил все__new__() черная магия в статический метод называетсяgetтакой, чтобы я мог позвонитьPhotograph.get(filename) и это будет только позвонитьPhotograph(filename) если имя файла не было уже вPhotograph.instances.

Кто-нибудь знает, где я ошибся здесь? Есть ли лучший способ сделать это?

Другой способ думать об этом состоит в том, что он аналогичен синглтону, за исключением того, что он не глобально синглтон, а только синглтон на имя файла.

Вот мой реальный код с использованием staticmethod get если вы хотите увидеть все это вместе.

Ответы на вопрос(3)

Ваш ответ на вопрос