3

I am following this tutorial on named tuple with specification of variable types. However, I modified the code (below), and even if I enter values of wrong types, there was no error message or programming break as a result. I understand you can write your own try/except to raise error exception, but is there a readily-available solution/syntax to enforce users entering the right type of variables.

from typing import NamedTuple

class Pet(NamedTuple):
    pet_name: str
    pet_type: str

    def __repr__(self):
        return f"{self.pet_name}, {self.pet_type}"

cleons_pet = Pet('Cotton', 'owl')
print('cleons_pet: ', cleons_pet)

cleons_pet_v2 = Pet(222, 1)
print('cleons_pet_v2: ', cleons_pet_v2)

# Output
cleons_pet:  Cotton, owl
cleons_pet_v2:  222, 1
[Finished in 0.1s]

2 Answers 2

3

The type hints in python will not be evaluated by python itself! See PEP484

While these annotations are available at runtime through the usual annotations attribute, no type checking happens at runtime. Instead, the proposal assumes the existence of a separate off-line type checker which users can run over their source code voluntarily.

There are at least two projects which offer offline type checking (mypy and pyre). You should definitely use them if you are using type hints in your project.

If you want to validate the input while running the application, you have to either convince the offline type checkers by validating the data by yourself or use a third-party library. I know of attrs, where you can use validators or type annotations for online validation.

Sign up to request clarification or add additional context in comments.

Comments

1

Since NamedTuple does not permit override of __new__ or __init__ it is not possible to perform validation during instance creation. To work around this constraint I add a generalized validation method to my NamedTuple classes and call it after the instance is created:

def validate_namedtuple_types(self):
    for field, annotation in self.__annotations__.items():
        if not isinstance(getattr(self, field), annotation):
            raise TypeError(f'provided value "{getattr(self, field)}" is wrong type ' + \
                            f'({type(getattr(self, field))}) for field {field} (should be {annotation})')

This can be added directly to a NamedTyple class or referenced as an external function e.g.

class Ethernet(NamedTuple):
    dst_addr: EthAddr | str
    src_addr: EthAddr
    type:     int     = 0x86DD
    validate_types = validate_namedtuple_types

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.