Custom String Formatter I've written my custom implementation of an f"" / .format(...). I started the project thinking it was going to be longer than three lines.

from typing import List, Union, AnyStr

def format_string(string: str, variables: List[Union[str, int, float, bool, complex]]) -&gt; str:
    """
    Formats the passed string with the passed list of variables

    &gt;&gt;&gt; format_string("Hello, [*]", ["Ben"])
    Hello, Ben

    :param string -&gt; str: String to be formatted
    :param variables -&gt; List[Union[str, int, float, bool, complex]]: List of variables to format into string

    :return str: Formatted string
    """
    for index, value in enumerate(variables):
        string = string.replace("[*]", str(value), 1)
    return string


My main question is if it's possible to make this a one-liner. It absolutely infuriates me that I have to use three. I spent a long time trying a mixture of * and ''.join to no avail. The code works, I would just like to shorten it up to one line. Of course, any and all feedback is appreciated and considered.

A secondary question is the method header. To represent variables, I have a List that can contain any types of variables. How would I go about representing this instead of having to list each type separately?
For the second point, since it's easier, typing has an Any:

from typing import List, Any
. . ., variables: List[Any], . . .


For the first, you're just doing a reduction over variables:

from typing import List, Any
from functools import reduce


def format_string(string: str, variables: List[Any]) -&gt; str:
    return reduce(lambda s, val: s.replace("[*]", str(val), 1), variables, string)


Although really, in a real use case, I'd still split this over three lines for clarity:

def format_string(string: str, variables: List[Any]) -&gt; str:
    return reduce(lambda s, val: s.replace("[*]", str(val), 1),
                  variables, 
                  string)


And honestly, I might just make that function var-arg instead of grouping things in a list to make it consistent with other format functions:

def format_string(string: str, *variables: Any) -&gt; str:
    return reduce(lambda s, val: s.replace("[*]", str(val), 1), variables, string)

&gt;&gt;&gt; format_string("[*] Hello [*]", 1, 2)
'1 Hello 2'


Note that when annotating a a var-arg parameter, you annotate the type of each element and ignore the type of the wrapping container (a tuple iirc). That means it's *variables: Any, not *variables: Tuple[... Any].



Of course though, whether or not this is better is a matter of taste, but this is the ideal use-case for reduce. Whenever you want to constantly reassign one thing in a simple loop, reduce is likely a good tool to look at.