Создание списка подклассов
Я хочу получить класс из list
добавьте к нему несколько атрибутов экземпляра и сделайте его хэшируемым. Какой хороший (быстрый и аккуратный) способ сделать это?
ОБНОВИТЬ:
Я удалил длинное объяснение варианта использования. Я также перенес связанную, но отдельную проблему в другой вопрос.
3 ответа
Решение
Этот код в порядке. Вы делаете копию списка, который может быть немного медленным.
def __hash__(self):
return hash(tuple(self.list_attribute))
У вас есть несколько вариантов, если вы хотите быть быстрее.
- хранить
list_attribute
как кортеж, а не список (после того, как он полностью построен) - Вычислите хэш один раз во время инициализации и сохраните значение хеша. Вы можете сделать это, потому что ваш класс неизменен, поэтому хеш никогда не изменится.
- Напишите свою собственную хэш-функцию. Вот хеш-функция для кортежа, сделайте что-то подобное.
Это скорее комментарий, чем ответ, но он слишком длинный, чтобы быть комментарием. Вот как можно получить доступ к атрибутам экземпляра изнутри __new__
:
class Data(tuple):
def __new__(klass, arg):
data_inst = tuple.__new__(klass, arg)
data_inst.min = min(data_inst)
data_inst.max = max(data_inst)
return data_inst
>>> d = Data([1,2,3,4])
>>> d
(1, 2, 3, 4)
>>> d.min
1
>>> d.max
4
>>> d1 = Data([1,2,3,4,5,6])
>>> d1.max
6
>>> d.max
4
Вы можете подать заявку tuple
в self
:
class State(list):
def __hash__(self):
return hash((self.some_attribute, tuple(self)))
tuple
-ную self
занимает примерно половину времени всего процесса хеширования:
from timeit import timeit
setup = "from __main__ import State; s = State(range(1000)); s.some_attribute = 'foo'"
stmt = "hash(s)"
print(timeit(stmt=stmt, setup=setup, number=100000))
setup = "r = list(range(1000))"
stmt = "tuple(r)"
print(timeit(stmt=stmt, setup=setup, number=100000))
печать
0.9382011891054844
0.3911763069244216