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]) -> 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]) -> 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) -> str:
return reduce(lambda s, val: s.replace("[*]", str(val), 1), variables, string)
>>> 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.