2016-11-16 2 views
0

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

Сравнивая эти «хэши», я хочу узнать, изменился ли объект с момента последнего сканирования.

Я нашел множество примеров того, как сделать объект хешируемым, но не столько о том, как вычислить хэш родительского класса.

Важно отметить, что сравнения выполняются во время различных исполнений. Я говорю это, потому что я думаю, что сравнение id() объекта, так как id/address объекта может отличаться для разных исполнений.

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

Если у меня был доступ к фактическим необработанным данным памяти, где хранится экземпляр и код класса, я мог бы просто вычислить хэш этого.

Любые идеи?

+0

Вы можете просто сгенерировать хеш '__dict__' собственности вашего объекта, если вы хотите знать, если он изменился с момента последней проверки. Я не думаю, что здесь важно учитывать его класс. – lucasnadalutti

+0

Я не уверен, какой случай не покрывается встроенным ['hash()'] (https://docs.python.org/2/library/functions.html#hash)? Можете ли вы расширить это? – TemporalWolf

+0

@TemporalWolf, если у вас есть 'foo', экземпляр' class Foo' и do 'foo.bar = 1',' hash (foo) 'будет генерировать значение, которое останется неизменным после того, как вы сделаете' foo.bar = 2'. OP хочет обнаружить такое изменение. – lucasnadalutti

ответ

1

Общая идея - сериализовать объект, а затем взять хэш. Тогда единственный вопрос - найти хорошую библиотеку. Давайте попробуем укроп:

>>>import dill 
>>>class a(): 
    pass 
>>>b = a() 
>>>b.x = lambda x:1 
>>> hash(dill.dumps(b)) 
2997524124252182619 
>>> b.x = lambda x:2 
>>> hash(dill.dumps(b)) 
5848593976013553511 
>>> a.y = lambda x: len(x) 
>>> hash(dill.dumps(b)) 
-906228230367168187 
>>> b.z = lambda x:2 
>>> hash(dill.dumps(b)) 
5114647630235753811 
>>> 

Выглядит хорошо?

укроп: https://github.com/uqfoundation

+0

Спасибо! Кажется, это сработало! Теперь у меня есть некоторые неприятности, вносящие его в счеты, но это другое дело;) – viterbi

0

Чтобы определить, был ли объект изменен, вы можете создать хэш своего представления JSON и сравнить с последним хешем, сгенерированным одним и тем же методом.

import json 

instance.foo = 5 
hash1 = hash(json.dumps(instance.__dict__, sort_keys=True)) 

instance.foo = 6 
hash2 = hash(json.dumps(instance.__dict__, sort_keys=True)) 

hash1 == hash2 
>> False 

instance.foo = 5 
hash3 = hash(json.dumps(instance.__dict__, sort_keys=True)) 

hash1 == hash3 
>> True 

Или, так как json.dumps дает нам строку, вы можете просто сравнить их вместо генерации хэша.

import json 

instance.foo = 5 
str1 = json.dumps(instance.__dict__, sort_keys=True) 

instance.foo = 6 
str2 = json.dumps(instance.__dict__, sort_keys=True) 

str1 == str2 
>> False 
+0

Я тестировал и, похоже, не работает ... опять же учитываются только переменные объектов ... если идти дальше и добавлять метод к классу или изменять некоторую константу, хэш остается тем же. ... – viterbi