Creating a bijection between integers and a set of strings I have a set of unique strings, I want to create a unique integer identifier for each string. 

Usage I want a function to move back and forth, if I give it an integer it returns the corresponding string and vice versa.

Here is how I am doing it

def str_to_int(S):
    integers = list(range(len(S)))
    my_dict = dict(zip(S,integers))
    rev_dict = dict(zip(integers,S))
    return my_dict, rev_dict


If I need to get the integer identifier of an item of S, I need to call the function and then the appropriate returned dictionary. 

I want something simpler, given an integer or a string, it knows, somehow automatically if it's an int or str and return the other identifier (i.e. if I give an int it returns the str identifier and vice versa). Is it possible to do it in a single function ? (if possible without being obliged to recreate dictionaries for each call)

Edit: I thought of doing to functions str_to_int(S:set, string:str)-&gt;int and int_to_str(S:set ,integer:int)-&gt;str but the problem is 1) that's two functions, 2) each time two dictionaries are created.
Since what you want is something a little more complicated than what a normal dictionary can do, I think you want to encapsulate all of this in a class that behaves the way you want the dict to behave.  You can make it "look like" a dict by implementing __getitem__, something like:

from typing import Dict, List, Set, Union, overload


class StringTable:
    """Associate strings with unique integer IDs."""

    def __init__(self, strings: Set[str]):
        """Initialize the string table with the given set of strings."""
        self._keys: List[str] = []
        self._ids: Dict[str, int] = {}
        for key in strings:
            self._ids[key] = len(self._keys)
            self._keys.append(key)

    @overload
    def __getitem__(self, o: int) -&gt; str: ...

    @overload
    def __getitem__(self, o: str) -&gt; int: ...

    def __getitem__(self, o: Union[int, str]) -&gt; Union[str, int]:
        """Accepts either a string or int and returns its counterpart."""
        if isinstance(o, int):
            return self._keys[o]
        elif isinstance(o, str):
            return self._ids[o]
        else:
            raise TypeError("Bad argument!")

    def __len__(self) -&gt; int:
        return len(self._keys)


Now you can use it like:

strings = {"foo", "bar", "baz"}
bijection = StringTable(strings)
for s in strings:
    print(s, bijection[s])
    assert bijection[bijection[s]] == s


etc.