5

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?

Veky
  • 2,646
  • 1
  • 21
  • 30
  • 1
    I am unclear what you want to do. Do you just want to change `__repr__`, or do you also want to change `__init__`, too? Because you don't need to override `__init__` if you only want to change `__repr__`. – TheBlackCat Apr 20 '15 at 15:09
  • Changing `__repr__` was priority. But I thought I might as well change the construction of new edges to remove unnecessary {}s, when I'm writing a new class. – Veky Apr 20 '15 at 15:17

1 Answers1

2

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. :-)

Veky
  • 2,646
  • 1
  • 21
  • 30