2013-07-26 3 views
1

У меня есть куча File объектов и куча Folder объектов. Каждая папка имеет файлы list. Теперь, иногда мне хотелось бы найти в какой папке какой-то файл. Я не хочу проходить через все папки и файлы, поэтому создаю папку dict file ->.Использовать python dict для поиска изменяемых объектов

folder = Folder() 
myfile = File() 
folder_lookup = {} 

# This is pseudocode, I don't actually reach into the Folder 
# object, but have an appropriate method 
folder.files.append(myfile) 
folder_lookup[myfile] = folder 

Проблема в том, что файлы являются изменяемыми объектами. Это приложение основано на факте. Я изменяю их свойства, и графический интерфейс уведомляется и обновляется соответствующим образом. Конечно, вы не можете помещать изменяемые объекты в dicts. Так что я пытался первым, чтобы сгенерировать хэш на основе текущего содержания, в основном:

def __hash__(self): 
    return hash((self.title, ...)) 

Это не работа, конечно, потому что, когда содержимое объекта изменился его хэш (и, таким образом, его личность) изменился, и все перепуталось. Мне нужен объект, который сохраняет свою личность, хотя его содержимое меняется. Я пробовал разные вещи, например, делать __hash__ return id(self), переопределяя __eq__ и так далее, но так и не нашел удовлетворительного решения. Одно из осложнений состоит в том, что вся конструкция должна быть подбираемой, поэтому мне нужно будет хранить id при создании, так как это может измениться при травлении, я думаю.

Поэтому я в основном хочу использовать идентификатор объекта (а не его состояние) для быстрого поиска данных, связанных с объектом. На самом деле я нашел очень хорошее pythonic обходное решение для своей проблемы, которое я мог бы опубликовать в ближайшее время, но я хотел бы посмотреть, будет ли кто-то еще придумать решение.

+2

Атрибут файлового объекта, сообщающий вам, в какой папке они не являются параметрами? – Jblasco

+0

Согласовано с Jblasco. Старайтесь иметь уникальный атрибут каждый раз, когда вы создаете новый объект File – Paco

+0

@Jblasco: Да, это мертвое простое питоническое обходное решение, с которым я пошел :-). Тем не менее, мне все еще интересно, есть ли способ сделать это с помощью внешнего dict. Одна причина: могут быть разные классы папок (каталоги, теги, интеллектуальные поиски). Я должен добавить специальный атрибут для каждого вида. – jdm

ответ

0

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

class dodgy(list): 
    def __init__(self, title): 
     self.title = title 
     super(list, self).__init__() 
     self.store = type("store", (object,), {"blanket" : self}) 
    def __hash__(self): 
     return hash(self.store) 

innocent_d = {} 
dodge_1 = dodgy("dodge_1") 
dodge_2 = dodgy("dodge_2") 
innocent_d[dodge_1] = dodge_1.title 
innocent_d[dodge_2] = dodge_2.title 

print innocent_d[dodge_1] 
dodge_1.extend(range(5)) 
dodge_1.title = "oh no" 
print innocent_d[dodge_1] 
+0

Это очень интересно, и я согласен, довольно коварный. Особенно то, что вы вкладываете в «магазин». Однако я никогда не нуждался в том, чтобы File/dodgy object был подклассом списка. Если это обычный подкласс объекта, по-видимому, можно просто использовать его в качестве ключа, если вы будете осторожны. – jdm

+0

Да, я выбрал объект списка, чтобы продемонстрировать его с помощью нераскрывающегося типа. – dilbert

0

ОК, все заметили чрезвычайно очевидный обходной путь (который взял мои несколько дней, чтобы придумать), просто положить атрибут File, который говорит вам, какие папки он находится. (Не волнуйтесь, это также, что я сделал.)

Но, оказывается, я работал под неправильными предположениями. Вы не должны использовать изменяемые объекты в качестве ключей, но это не значит, что вы не можете (диаболический смех)! Реализация по умолчанию __hash__ возвращает уникальное значение, вероятно, полученное из адреса объекта, которое остается постоянным во времени. И по умолчанию __eq__ следует тому же понятию идентичности объекта.

Итак, вы можете поместить изменяемые объекты в dict, и они работают как ожидалось (если вы ожидаете равенства на основе экземпляра, а не по значению).

Смотрите также: I'm able to use a mutable object as a dictionary key in python. Is this not disallowed?

У меня были проблемы, потому что был травление/unpickling объекты, которые, конечно, изменили хешей. В конструкторе можно создать уникальный идентификатор и использовать его для равенства и получения хэша для преодоления этого.

(Для любопытных, относительно того, почему может потребоваться такой запрос «на основе идентификации экземпляра»: я экспериментировал с видом "object database". У вас есть чистые объекты python, поместите их в списки/контейнеры, и может определять индексы атрибутов для более быстрого поиска, сложных запросов и т. д. Для внешних ключей (отношения 1: n) я могу просто использовать контейнеры, но для обратной ссылки я должен придумать что-то умное, если я не хочу изменить объекты на странице n.)