2

I want to allow type hinting using Python 3 to accept instances which are children of a given class. I'm using the enforce module to check the function typing. E.g.:

import abc
class A(metaclass=abc.ABCMeta)
      pass
class B(A)
      def __init__(self,a)
      self.a = a
      pass
x = B(3)

@enforce.runtime_validation
def function(x:A)
     print(x.a)

but it seems like python 3 doesn't allow for this syntax, returning:

Argument 'x' was not of type < class 'A' >. Actual type was B.

Any help?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Lorenzo
  • 25
  • 1
  • 4
  • Python itself has no opinion, I think. Is this message coming from mypy, or something else? – brunns Apr 26 '19 at 14:32
  • @brunns no, I'm using enforce – Lorenzo Apr 26 '19 at 14:40
  • @James I think it's a different case, in the question you cite they're looking for a function accepting subclasses, I want to use an instance instead. An instance of a subclass of A – Lorenzo Apr 26 '19 at 14:40
  • Can you update the question to say that it's enforce that's giving you the message? – brunns Apr 26 '19 at 14:51
  • This help? https://stackoverflow.com/questions/46092104/subclass-in-type-hinting – brunns Apr 26 '19 at 15:00
  • Could you try configuring enforce using enforce.config({'mode ': 'covariant'}). Let us know if that works and if so I'll write up an explanation as an answer – James Apr 26 '19 at 15:01
  • @James Thanks, enforce.config({'mode ': 'covariant'}) works for me! – Lorenzo Apr 26 '19 at 15:06

2 Answers2

0

By default enforce applies invariant type checking. The type has to match directly - or an error is thrown.

In order for an instance of a subclass to be accepted, the mode can be changed to covariant by adding :

enforce.config({'mode ': 'covariant'})

at a point in the code that is executed before any type checking is done (i.e. near the start).

Other modes are available as described in the documentation.

For further informations see : https://github.com/RussBaz/enforce

James
  • 3,252
  • 1
  • 18
  • 33
0

Use a bound TypeVar:

import abc
from typing import TypeVar

class A(metaclass=abc.ABCMeta):
      pass

      
class B(A):
      def __init__(self, a):
          self.a = a


AType = TypeVar('AType', bound=A)
x = B(3)


def function(x: AType):
    print(x.a)

However, this will still produce an error with e.g. MyPy, since a generic A does not have an attribute a (but this is a different issue).

Richard Neumann
  • 2,986
  • 2
  • 25
  • 50