Создание hash для типа python
Допустим такую структуру:
class Base:
id = 0
def __type_hash__(cls):
return hash((Base,cls.id))
def __init__(self,value)
self.value = value
def __hash__(self):
return hash(value)
class C87(Base):
id = 0x87
class CA0(C87):
id = 0xA0
class CFoo(C87):
pass
class CBar(CA0):
pass
вот хочу использовать класс в списках и ключах чтоб например
C87 in [CFoo] == True
CFoo in [Base, CA0] == False
__type_hash__
- плейсхолдер для неизвестной магии. Экземпляры чтоб сравнивались по value, а классы по id.
Ответы (1 шт):
Автор решения: Amgarak
→ Ссылка
Если я правильно понял вашу идею:
Через метакласс мы можем переопределить методы самого класса и будет
hash/сравнение
через id.В то время как экземпляры переопределят методы обратно, и будут использоваться уже те что определены в самом классе, а следовательно всё уже будет работать через value.
class BaseMeta(type):
def __eq__(cls, other):
if isinstance(other, type):
return cls.id == getattr(other, 'id', None)
return False
def __hash__(cls):
return hash(cls.id)
class Base(metaclass=BaseMeta):
id = 0
def __init__(self, value):
self.value = value
def __hash__(self):
return hash(self.value)
def __eq__(self, other):
if isinstance(other, Base):
return self.value == other.value
return False
class C87(Base):
id = 0x87
class CA0(C87):
id = 0xA0
class CFoo(C87):
pass
class CBar(CA0):
pass
print(hash(C87) == hash(CFoo)) # True
print(hash(C87) == hash(CA0)) # False
print(hash(CBar) == hash(CA0)) # True
print(C87 == CFoo) # True
print(CFoo == CA0) # False
foo1 = CFoo(100)
foo2 = CFoo(100)
bar1 = CBar(200)
bar2 = CBar(100)
print(foo1 == foo2) # True
print(foo1 == bar1) # False
print(hash(foo1) == hash(bar1)) # False
print(hash(foo1) == hash(bar2)) # True
print(C87 in [CFoo]) # True
print(CFoo in [Base, CA0]) # False
my_dict = {foo1:"78", foo2:"90", bar1:"54", bar2:"13"}
print(my_dict) # {<__main__.CFoo object at 0x7a26419d10>: '13', <__main__.CBar object at 0x7a26419850>: '54'}
print(my_dict[foo1]) # 13
my_dict2= {C87:"78", CFoo:"90", CBar:"54", CA0:"13"}
print(my_dict2) # {<class '__main__.C87'>: '90', <class '__main__.CBar'>: '13'}
print(my_dict2[C87]) # 90