Создание списка подклассов

Я хочу получить класс из 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
Другие вопросы по тегам