Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Narrowing down type hints in children

I was wondering if putting tighter constraints on the type hints in child classes is bad practice or not. Consider the following example

from typing import List, Tuple
from abc import abstractmethod


class Foo:
    @abstractmethod
    def print_stuff(self, items: List[str]):
        """print some list."""


class Bar(Foo):
    def print_stuff(self, items: Tuple[str, str]):
        print(f"Items: {items}, always 2.")
        
class Baz(Foo):
    def print_stuff(self, items: Tuple[str, str, str]):
            print(f"Items: {items}, always 3.")

Here the base class expects some list of strings. In Bar the method only allows exactly two strings, and in Baz exactly three. Is this increased restriction bad practice?
Thank you!

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

You can use the ellipsis dots to indicate the number of arguments in the tuple is variable. You should avoid using List in your parent class and Tuple in your child class as they are fundamentally different types.

from typing import List, Tuple
from abc import abstractmethod

class Foo:
    @abstractmethod
    def print_stuff(self, items: Tuple[str, ...]):
        """print some list."""

class Bar(Foo):
    def print_stuff(self, items: Tuple[str, str]):
        print(f"Items: {items}, always 2.")
        
class Baz(Foo):
    def print_stuff(self, items: Tuple[str, str, str]):
        print(f"Items: {items}, always 3.")

This is still not great practice as the Bar and Baz return different lengths of tuples which violates Liskov substitution; mypy will probably throw an error.

The real question is: does it have to be a tuple, or is any sequence acceptable? Then you should use:

from typing import Sequence
from abc import abstractmethod


class Foo:
    @abstractmethod
    def print_stuff(self, items: Sequence[str]):
        """print some list."""

class Bar(Foo):
    def print_stuff(self, items: Sequence[str]):
        print(f"Items: {items}, always 2.")
        
class Baz(Foo):
    def print_stuff(self, items: Sequence[str]):
        print(f"Items: {items}, always 3.")
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading