0

I want to create a class Packet identical to list except that it can be compared to int objects. Comparing to an int shall return the same result as comparing to a Packet containing only that int. The following definition does what I want.

class Packet(list):
    def __init__(self, iterable=()):
        super().__init__()
        for x in iterable:
            if isinstance(x, list):
                self.append(type(self)(x))
            else:
                self.append(x)

    def __lt__(self, x):
        if isinstance(x, int):
            return self.__lt__(type(self)([x]))
        return super().__lt__(x)

    def __le__(self, x):
        if isinstance(x, int):
            return self.__le__(type(self)([x]))
        return super().__le__(x)

    def __eq__(self, x):
        if isinstance(x, int):
            return self.__eq__(type(self)([x]))
        return super().__eq__(x)

    def __ne__(self, x):
        if isinstance(x, int):
            return self.__ne__(type(self)([x]))
        return super().__ne__(x)

    def __ge__(self, x):
        if isinstance(x, int):
            return self.__ge__(type(self)([x]))
        return super().__ge__(x)

    def __gt__(self, x):
        if isinstance(x, int):
            return self.__gt__(type(self)([x]))
        return super().__gt__(x)

a = Packet([2, 3, 5])
b = Packet([[2], 3, [[5]]])
c = Packet([2, [3, 4]])
d = 2

assert a == b
assert a < c
assert a > d
assert b < c
assert b > d
assert c > d

However, this is rather repetitive; I wrote basically the same code six times. There's got to be a way to do this in a loop or at least using a decorator, right? How can I create an identical class without repeating myself?

schtandard
  • 387
  • 4
  • 18

1 Answers1

0

I hope it works;

def proof(self):
    return "this is __str__ overriding"


def same_func(self, x):
    if isinstance(x, int):
        return self.__gt__(type(self)([x]))
    return super().__gt__(x)


class SuperPacket(list):
    def __init__(self):
        overrides_functions = ["__lt__", " __le__", "__eq__", "__ne__", "__ge__", "__gt__"]
        for func in overrides_functions:
            setattr(SuperPacket, func, same_func)
        setattr(SuperPacket, '__str__', proof)
        super().__init__()


hello = SuperPacket()
print(hello)

based on the comments, I offer to you another method;

def same_func(self, x):
    if isinstance(x, int):
        return self.__gt__(type(self)([x]))
    return super().__gt__(x)


class SuperPacket(list):
    def __init__(self, iterable=()):
        self.__gt__ = same_func
        self.__lt__ = same_func
        self.__le__ = same_func
        self.__ne__ = same_func
        self.__ge__ = same_func
        self.__gt__ = same_func
        self.__eq__ = same_func
        super().__init__()
        for x in iterable:
            if isinstance(x, list):
                self.append(type(self)(x))
            else:
                self.append(x)


hello = SuperPacket([2])
print(hello == [2])
# True
Sezer BOZKIR
  • 534
  • 2
  • 13
  • Sadly, it does not. I get `RuntimeError: super(): __class__ cell not found`. I added some tests to my question that trigger the problem. – schtandard Dec 14 '22 at 09:37
  • Also, this only changes the methods of the class upon instantiation of the first object, right? While this would not be an issue functionally, it seems a bit odd to me. Changing them before (when defining the class) would seem cleaner. – schtandard Dec 14 '22 at 09:39
  • I added another solution, would you re-try it? – Sezer BOZKIR Dec 14 '22 at 11:04
  • I'm afraid I don't understand your second suggestion. Doesn't this just make all comparison functions behave as `>`? Accordingly, it does not pass the tests I provided. Actually, it doesn't even pass the `>` tests. – schtandard Dec 16 '22 at 12:23
  • I checked the question and answer after your comment. We can shorten this code if we pass the filter function as a parameter, it will work, but this will seriously damage the legibility of the code. When I examined the List library, I saw that even core developers wrote these functions recursively. In order to profit a few lines, I think we should not make the code ugly. The first of the "Zen of Python" rules is "Beautiful is better than ugly." So I think shortening this code any more would hurt its legibility. – Sezer BOZKIR Dec 16 '22 at 14:53