2

In my case, I want to define a custom class (called WordTuple) which is a subclass of the tuple class. The elements of this custom tuple must all be of another custom class(called Word).

I know that this question (How to make an iterable class in Python in which only a specific type is allowed to be the element?) is similar, but the answer is not what I am looking for, nor it is very clear to me.

class Word(str):
    pass

class WordTuple(tuple):
    # Here whatever is necessary for the elements of this particular tuple
    # to be all members of the class 'Word'
    pass
antoHuman
  • 159
  • 7
  • Can't you enforce it in the __init__ ? Each time this class is initialized you can verify the data types using isinstance – orizis Jul 23 '17 at 16:15
  • 1
    @orizis The standard built-in immutable types get initialized in the `__new__` method rather than in `__init__`. There's more info about this [here](https://stackoverflow.com/questions/35452178/what-can-init-do-that-new-cannot) – PM 2Ring Jul 23 '17 at 18:01
  • @PM2Ring Cool, good to know. Thanks for alerting me! – orizis Jul 23 '17 at 18:19

1 Answers1

3

Because a tuple is immutable you only need to validate the objects when creating the tuple. You can do so in a custom __new__ method:

class WordTuple(tuple):
    def __new__(cls, *objs):
        if not all(isinstance(o, Word) for o in objs):
            raise TypeError('WordTuple can only contain Word instances')
        return super().__new__(cls, objs)

Demo:

>>> WordTuple('a', 'b')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in __new__
TypeError: WordTuple can only contain Word instances
>>> WordTuple(Word('a'), Word('b'))
('a', 'b')
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343