2

Consider the following python file test.py:

def accepts_string(s: str):
    pass

If I open a python shell, import this function and then grab the function's parameter s and its annotation I get a string literal.

>>> import inspect
>>> from test import accepts_string
>>> inspect.signature(accepts_string).parameters['s'].annotation
'str'

However, if I define the function in the shell - I get the expected results of an actual "class type".

>>> import inspect
>>> def accepts_string(s: str):
...    pass
...
>>> inspect.signature(accepts_string).parameters['s'].annotation
<class 'str'>    

I would expect to always get the later results and I'm having trouble reconciling the different results based on whether the function is imported vs. defined live.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • 2
    I get `` consistently, do you have e.g. `from __future__ import annotations` anywhere? – jonrsharpe Jun 05 '22 at 19:46
  • I don't know why BUT It seems that `typing.get_type_hints` reliably returns "class type" for a function parameter. I assume that something happens to the `.__annotation__` dictionary on the import process that should be avoided if you want to test if a function accepts an argument of a certain type - which was my intended goal. https://docs.python.org/3.9/library/typing.html?highlight=__annotations__#typing.get_type_hints – Peter Wensel Jun 05 '22 at 19:57
  • @jonrsharpe I do... at the top of the file. – Peter Wensel Jun 05 '22 at 19:58
  • Well that makes showing it _without_ that not the best example. Why did you add that if _not_ for the explicit behaviour it enables? – jonrsharpe Jun 05 '22 at 19:58
  • @jonrsharpe Oh Wild... Yes - the results differ IF `from __future__ import annotations` are included on the file being imported! `typing.get_type_hints` circumvents this difference however. – Peter Wensel Jun 05 '22 at 19:59
  • @jonrsharpe Because I didn't have a full understanding on what that behavior entailed and its affects >.< Thanks for commenting, appreciate it! – Peter Wensel Jun 05 '22 at 20:03
  • 1
    Not so much "wild" as ["the documented behaviour"](https://docs.python.org/3/library/__future__.html); `get_type_hints` doesn't _"circumvent"_ it, it [explicitly](https://docs.python.org/3/library/typing.html#typing.get_type_hints) evaluates forward references. – jonrsharpe Jun 05 '22 at 20:03
  • @PeterWensel yes, because that is the whole point of `from __future__ import annotations`. Unfortunately, this whole situation is a bit of a mess. The `__future__` behavior will become the default behavior, it was supposed to in Python 3.10, but it got delayed, not sure the current status – juanpa.arrivillaga Jun 05 '22 at 20:03

1 Answers1

3

This issue was due to a lack of understanding what from __future__ import annotations was doing. This was included at the top of my file and was omitted from the initial example I gave. Apologies for not realizing that when making this post.

As a user pointed out in the comments:

The future behavior will become the default behavior, it was supposed to in Python 3.10, but it got delayed, not sure the current status

I think I will need to use typing.get_type_hints anyway to reliably grab annotations for functions for future python versions.