eng2019
eng2019

Reputation: 1035

Using NamedTuple inside NamedTuple with Optional typing

Is it possible to create NamedTuple inside NamedTuple like this?

from typing import NamedTuple, List, Optional
class BabyData(NamedTuple):
    name: str
    age: int
    body_measurement: Optional[NamedTuple('height': List, 'weight': List)] = None

Thanks!

Upvotes: 0

Views: 141

Answers (2)

Romain
Romain

Reputation: 21898

The example provided outputs an error at run time.

body_measurement: Optional[NamedTuple('height': List, 'weight': List)] = None
                                                  ^
SyntaxError: invalid syntax

To fix it you need

from typing import NamedTuple, List, Optional

class BabyData(NamedTuple):
    name: str
    age: int
    body_measurement: Optional[
        NamedTuple("BodyMeasurement", [("height", List), ("weight", List)])
    ] = None

if __name__ == "__main__":
    baby = BabyData(
        name="john", age=1, body_measurement={"height": [50, 51], "weight": [3, 3.5]}
    )
    print(baby)

# BabyData(name='john', age=1, body_measurement={'height': [50, 51], 'weight': [3, 3.5]})

In fact you try to mix two ways of defining NamedTuple. As per the documentation.

class Employee(NamedTuple):
    name: str
    id: int
# This is equivalent to:

Employee = collections.namedtuple('Employee', ['name', 'id'])

You should also consider using dataclasses, see the foxyblue's answer.

Upvotes: 1

s3bw
s3bw

Reputation: 3049

You might want to use dataclasses for this use case instead:

from typing import Optional
from dataclasses import dataclass


@dataclass
class Measurements:

    height: list
    weight: list


@dataclass
class Baby:

    name: str
    age: int
    body: Optional[Measurements] = None

You can also have classes reference themselves:

from __future__ import annotations

from typing import Optional
from dataclasses import dataclass


@dataclass
class Person:

    name: str
    age: int
    parent: Optional[Person] = None

Upvotes: 4

Related Questions