grantjenks / python-sortedcontainers

Python Sorted Container Types: Sorted List, Sorted Dict, and Sorted Set
http://www.grantjenks.com/docs/sortedcontainers/
Other
3.51k stars 203 forks source link

Problem with inheritance from SortedSet #224

Closed puiseux closed 1 year ago

puiseux commented 1 year ago

Hello, I create a class Index that inherits from SortedSet. But Union does not work as expected. Here is the piece of code :

from sortedcontainers import SortedSet

class Index(SortedSet):
    def __init__(self, r:range or list or tuple or np.ndarray):
        super(Index, self).__init__(r)

if __name__=='__main__' :
    S = Index([])
    S1 = Index([2,3,0])
    print(S.union(S1))

and here is the result :

Index([])
Index([0, 2, 3])
Traceback (most recent call last):
  File "/Users/puiseux/GitHub/fonctions-discretes/src/py3/index.py", line 27, in <module>
    print(S.union(S1))
  File "/Users/puiseux/opt/miniconda3/lib/python3.9/site-packages/sortedcontainers/sortedset.py", line 658, in union
    return self.__class__(chain(iter(self), *iterables), key=self._key)
TypeError: __init__() got an unexpected keyword argument 'key'

Notice that if I replace Index with SortedSet, it works perfectly :

SortedSet([])
SortedSet([0, 2, 3])
SortedSet([0, 2, 3])
puiseux commented 1 year ago

Well, it looks like a bug in sortedset.py : SortedSet.union() calls SortedSet.__class__(x,k=self._key) with two arguments. But this __class__() property is defined in object.__class__(x) from builtins.py and requires only one unique argument. So I just override SortedSet.union() (locally) like this :

    def union(self, *iterables):
        # return self.__class__(chain(iter(self), *iterables), key=self._key)
        return self.__class__(chain(iter(self), *iterables))

Like this, it looks OK. But it's an ugly solution !

puiseux commented 1 year ago

Well, a better solution is not to override SortedSet.union(), but to declare Index.__init__(iterable=None, key=None) with **key** argument.

grantjenks commented 1 year ago

The init method of SortedSet adds an optional key parameter. Your subclass version is taking that away which is going to cause issues. See https://stackoverflow.com/questions/6034662/python-method-overriding-does-signature-matter for a description of the issue.