Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Customizing immutable types in Python [duplicate]

Let's say I want a custom frozenset with 2 elements, that iterates, hashes, compares, and has various other nice operations as a frozenset, but prints differently.

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

I can inherit, or I can delegate, but in neither case I get what I want.

If I inherit literally, there seems to be no way I can write __init__, because my parent is immutable. I can just write:

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

but then I get a proper frozenset and cannot customize its __repr__, which is what I wanted to do. I cannot make super() to work here in any nice way.

If I delegate, I can override __getattr__ or __getattribute__, but none of them really works when for example __iter__ is sought. I guess special methods are too special here. The only solution I currently have is to manually delegate every special method I can think of, but surely there must be a better way. Any ideas?

like image 743
Veky Avatar asked Oct 31 '22 06:10

Veky


1 Answers

Stupid me. It works now. If someone wants to know how to do it, here it is:

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)

The error was that I called super().__new__({a, b}) thinking that it will transmogrify my cls in the same way it does with self, when called without arguments. Of course, __new__ being implicitly classmethod didn't help. :-)

like image 193
Veky Avatar answered Nov 09 '22 05:11

Veky