# The AnyStr type variable

DevFeed: [The AnyStr type variable](<https://devfeed.tech/articles/the-anystr-type-variable-38897.md>)

Original publisher: [Read original article](<http://neopythonic.blogspot.com/2016/05/the-anystr-type-variable.html>)

Author: Guido van Rossum (noreply@blogger.com)

Published: 2016-05-17T16:53:00Z

Content type: tutorial

Language: en

Sources: [Guido van Rossum](<https://devfeed.tech/sources/guido-van-rossum.md>)

Topics: [Python](<https://devfeed.tech/topics/python.md>), [Polymorphism](<https://devfeed.tech/topics/polymorphism.md>), [function](<https://devfeed.tech/topics/function.md>), [Variable](<https://devfeed.tech/topics/variable.md>), [networking](<https://devfeed.tech/topics/networking.md>)

Tags: [bug](<https://devfeed.tech/tags/bug.md>), [debugging](<https://devfeed.tech/tags/debugging.md>), [function](<https://devfeed.tech/tags/function.md>), [polymorphism](<https://devfeed.tech/tags/polymorphism.md>), [python](<https://devfeed.tech/tags/python.md>), [types](<https://devfeed.tech/tags/types.md>)

## AI overview

A tutorial on Python type annotations uses a parenthesize function to explain polymorphism across str and bytes, the Union type, and how static type checking exposes a bytes-versus-str bug. It introduces AnyStr as the subject of a separate discussion related to PEP 484 and the __fspath__() protocol.

## Source excerpt

The AnyStr type variable I was drafting a blog post on how to add type annotations for the new __fspath__() protocol (PEP 519) when I realized that I should write a separate post about AnyStr . So here it is. A simple function on strings Let's write a function that surrounds a string in parentheses. We'll put it in a file named demo.py : def parenthesize(s): return '(' + s + ')' It works, too: >>> from demo import parenthesize >>> print(parenthesize('hola')) (hola) Of course, if you pass it something that's not a string it will fail: >>> parenthesize(42) Traceback (most recent call last): File "demo.py", line 1, in File "demo.py", line 2, in parenthesize TypeError: Can't convert 'int' object to str implicitly Adding type annotations Using PEP 484 type annotations we can clarify our little function's signature: def parenthesize(s: str) -> str: return '(' + s + ')' Nothing to it, right? Even if you've never heard of PEP 484 before you can guess what this means. (Note that PEP 484 also says that the runtime behavior is unchanged. The calls I showed above will still have exactly the same effect, including the TypeError raised by parenthesize(42) .) Polymorphic functions Now suppose this is actually part of a networking app and we need to be able to parenthesize byte strings as well as text strings. Here's how you'd implement that: def parenthesize(s): if isinstance(s, str): return '(' + s + ')' elif isinstance(s, bytes): return b'(' + s + b')' else: raise TypeError(f"That's not a string, it's a {type(s)}") # See PEP 498 With a fancy word we call that a polymorphic function. How do you write a signature for such a function? For the answer we have to dive a little deeper into PEP 484. It defines a nifty operator named Union that lets us state that a type can be either this or that (or something else). In our case, it's either str or bytes , so we can write it like this: from typing import Union def parenthesize(s: Union[str, bytes]) -> Union[str, bytes]: if isinstance(s,