0

I am trying to do type enforcement in Python 3.8 but unable to enforce type bounds. Let's consider the following example:

class Animal(object): pass
class Cat(Animal): pass
class Dog(Animal): pass

# now want a list of only cats
list_of_cats:Cat = list()

list_of_cats.append(Cat())
list_of_cats.append(Dog()) # this should not be allowed

for animal in list_of_cats:
  print(type(animal))

---- OUTPUT -----
<class '__main__.Cat'>
<class '__main__.Dog'>

Is there a way to enforce type bounds, using language features, in Python 3.8 (like Scala)?

Georgy
  • 12,464
  • 7
  • 65
  • 73
Neel
  • 9,913
  • 16
  • 52
  • 74
  • Can you clarify what you are trying to achieve? Do you want this code to be rejected by a type checker such as MyPy, or do you want an error to be thrown at runtime? Note that the annotation ``list_of_cats:Cat = list()`` is nonsensical, since ``list`` is not compatible with ``Cat``. Did you mean ``list_of_cats: List[Cat] = list()``? – MisterMiyagi Sep 16 '20 at 13:27
  • Does this answer your question? [Type hinting a collection of a specified type](https://stackoverflow.com/questions/24853923/type-hinting-a-collection-of-a-specified-type) – MisterMiyagi Sep 16 '20 at 13:27

1 Answers1

0

It depends on what you are trying to do, but for the simple examples like this,
you can create a custom class that does validation for the method.

class Animal(object): pass

class Cat(Animal): pass

class Dog(Animal): pass

class CatList(list):
    def append(self, item):
        if isinstance(item, Cat):
            super().append(item)
        else:
            print(f'Only cats are allowed, {item} not appended')

# now want a list of only cats, use CatList class
list_of_cats: Cat = CatList()

list_of_cats.append(Cat())
list_of_cats.append(Dog())  # this should not be allowed

for animal in list_of_cats:
    print(type(animal))
Only cats are allowed, <__main__.Dog object at 0x0000016CF590A4C0> not appended
<class '__main__.Cat'>

Note that this is just an example that validates the append method only.

ywbaek
  • 2,971
  • 3
  • 9
  • 28