2015-04-20 29 views
5

Załóżmy, że chcę niestandardowy frozenset z 2 elementami, który wykonuje iteracje, hasze, porównuje i ma różne inne ładne operacje jako zamrożone, ale drukuje inaczej.Dostosowywanie niezmiennych typów w języku Python

>>> p = edge(5, 7) 
>>> p == edge(7, 5) 
True 
>>> p 
edge(5, 7) 

Mogę dziedziczyć, lub mogę delegować, ale w żadnym przypadku nie dostaję tego, czego chcę.

Jeśli dziedziczę dosłownie, wydaje się, że nie ma mowy o napisaniu __init__, ponieważ mój rodzic jest niezmienny. I może wystarczy napisać:

class edge: 
    def __new__(cls, a, b): 
     return frozenset({a, b}) 

ale potem dostaję właściwego frozenset i nie można dostosować jego __repr__, czyli to, co chciałem zrobić. Nie mogę sprawić, aby super() działało tutaj w jakikolwiek przyjemny sposób.

Jeśli deleguję, mogę przesłonić __getattr__ lub __getattribute__, ale żadna z nich nie działa tak naprawdę, gdy szuka się na przykład __iter__. Sądzę, że specjalne metody są tutaj zbyt szczególne. Jedynym rozwiązaniem, jakie mam obecnie, jest ręczne delegowanie każdej specjalnej metody, jaką mogę wymyślić, ale z pewnością musi istnieć lepszy sposób. Jakieś pomysły?

+1

Nie jestem pewien, co chcesz zrobić. Czy chcesz zmienić '__repr__', czy też chcesz również zmienić' __init__'? Ponieważ nie ma potrzeby zastępowania '__init__', jeśli chcesz tylko zmienić' __repr__'. – TheBlackCat

+0

Zmiana '__repr__' była priorytetem. Ale pomyślałem, że równie dobrze mogę zmienić konstrukcję nowych krawędzi, aby usunąć niepotrzebne {} s, gdy piszę nową klasę. – Veky

Odpowiedz

2

Głupi mnie. Teraz działa. Jeśli ktoś chce wiedzieć, jak to zrobić, to jest tutaj:

class pair(frozenset): 
    def __new__(cls, a, b): 
     return super().__new__(cls, {a, b}) 
    def __repr__(self): 
     a, b = sorted(self) 
     return "{} & {}".format(a, b) 

Błąd było to, że nazwałem super().__new__({a, b}) myśląc, że będzie to transmogrify mój cls w taki sam sposób, w jaki robi z self, gdy wywołana bez argumentów. Oczywiście, __new__ będąc domyślnie metodą klasyczną, nie pomogło. :-)