0

I'm trying to inherit a hashable iterable such as a tuple. I want to also have metadata in the form of **kwargs but I'm getting a TypeError

Before I add **metadata:

class Collection(tuple):
    def __init__(self, pair):#, **metadata):
#         self.metadata = metadata
        self.pair = tuple(pair)
pair_1 = Collection(["Darth Plagueis", "Darth Sidious"])
pair_1   
# ('Darth Plagueis', 'Darth Sidious')

After I add **metadata:

class Collection(tuple):
    def __init__(self, pair, **metadata):
        self.metadata = metadata
        self.pair = tuple(pair)
pair_1 = Collection(["Darth Plagueis", "Darth Sidious"], affiliation="Sith")
# ---------------------------------------------------------------------------
# TypeError                                 Traceback (most recent call last)
# <ipython-input-119-f40b020d268d> in <module>
#      11         self.metadata = metadata
#      12         self.pair = tuple(pair)
# ---> 13 pair_1 = Collection(["Darth Plagueis", "Darth Sidious"], affiliation="Sith")
#      14 pair_1
#      15 # ('Darth Plagueis', 'Darth Sidious')

# TypeError: tuple() takes at most 1 argument (2 given)
# ​
O.rka
  • 29,847
  • 68
  • 194
  • 309
  • see https://stackoverflow.com/questions/1565374/subclassing-tuple-with-multiple-init-arguments – Pratik Oct 17 '19 at 05:28
  • @PratikGandhi it's not clear how to adapt to my situation. – O.rka Oct 17 '19 at 05:32
  • first you should check what you get in variables - `print(pair, metadata)` – furas Oct 17 '19 at 05:41
  • Do you really need to inherit for this, or do you just want your own type to be hashable? Because you do that by implementing `__hash__`. But it's not a good idea to have something be both hashable and mutable. Consider converting the metadata into a `namedtuple` using the keys as field names. Something like: `def make_nt(**kwargs): return collections.namedtuple('_', kwargs.keys())(*kwargs.values())` should do the trick. – Karl Knechtel Oct 17 '19 at 06:02

1 Answers1

3

To override tuple class you need to place the super initialization in __new__ method.

class Collection(tuple):
    def __new__(self, pair, **metadata):
        return super(Collection, self).__new__(self,tuple(pair))
    def __init__(self, pair, **metadata):
        self.metadata = metadata
        self.pair = tuple(pair)
>>> pair_1 = Collection(["Darth Plagueis", "Darth Sidious"], affiliation="Sith")
>>> pair_1.pair
('Darth Plagueis', 'Darth Sidious')
>>> pair_1.metadata
{'affiliation': 'Sith'}
Sayandip Dutta
  • 15,602
  • 4
  • 23
  • 52