0

I would like to set up an abstraction where I would like to only allow the sub datatypes of Foo to be passed in parts of my application. All of these really are typed NamedTuples, as they carry no functionality. This leads me to have Foo inherit from typing.NamedTuple, and add no additional functionality to Foo. My issue is when instantiating subtypes of Foo, I am greeted with an error.

Consider the following snippet

from typing import NamedTuple


class Foo(NamedTuple):
    pass


class Bar(Foo):
    a: int
    b: str
        
        
class Baz(Foo):
    one_thing: float
    another_thing: float

bar = Bar(4, "sdlfkjsdfkj")
print(bar)

The output of the snippet will be the following error...

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-20-b0f9b9293905> in <module>
     15     another_thing: float
     16 
---> 17 bar = Bar(4, "sdlfkjsdfkj")
     18 print(bar)

TypeError: __new__() takes 1 positional argument but 3 were given

However if I let Bar inherit directly from typing.NamedTuple then I am able to get the following snippet to function properly

class Bar(NamedTuple):
    a: int
    b: str
        
bar = Bar(4, "sdlfkjsdfkj")
print(bar)
>>> Bar(a=4, b='sdlfkjsdfkj')

Does this mean that for each data class definition (such as Bar or Baz) I have to inherit from typing.NamedTuple? Why can I not factor that out to a top level class?

Many Thanks in Advance!

FinnM
  • 394
  • 1
  • 3
  • 17
  • You cannot inherit from a class that inherits from `NamedTuple`. I also wished it were otherwise. Because a `Named Tuple` is at heart just a tuple, it's a bit unclear what the semantics of subclassing it would mean. – Frank Yellin Nov 09 '20 at 23:55
  • I'm not really sure what overall problem you're trying to solve this way, but maybe dataclasses could help? – Karl Knechtel Nov 09 '20 at 23:56
  • 1
    Because `typing.NamedTuple` is not a true class. Note, `isinstance(typing.NamedTuple, Foo())` is *false*. Basically, `NamedTuple` uses metaclass magic to generate a class that inherits from *tuple*. It's not very nice, but "practicality beats purity". See [this answer I wrote to a related question](https://stackoverflow.com/questions/60707607/weird-mro-result-when-inheriting-directly-from-typing-namedtuple/60883973#60883973) – juanpa.arrivillaga Nov 10 '20 at 00:01
  • Note that logically, ``NamedTuple`` subtypes may not have different attributes. A (named) tuple allows direct (attribute) item access *and* (attribute) item unpacking, meaning that both the count and order of attributes is guaranteed. A subclass adding attributes fails that. – MisterMiyagi Nov 11 '20 at 09:51

0 Answers0