Python Forum
dynamic f-string example
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
dynamic f-string example
#1
you might want to put this script in your python examples folder. you won't likely ever need to do this, but if some day you need to dynamically change the format of an f-string at run time (normally, python constructs code from an f-string at compile time when it reads in the source file), this can be a great reminder example of how to set it up.
silly = 'crazy'
exs = ['hellp {silly} world',
"""hey {silly}, this script is {silly.upper()}!""",
"1 + 1 = {1+1} ... how {silly}!"]
for ex in exs:
    result = eval(f'f{ex!r}')
    print(result)
always use a trusted source of all characters for an f-string format. using untrusted sources like user input over the internet can get your script exploited by the black hats.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#2
I really like f-strings, but this looks like a Frankenstein.

If I prepare some strings, before I do not have all data available, then I just use the format method for it. I also dislike the nesting of f-strings. It makes sense to control also the parameters of formatting, but afterwards it looks horrible. I always try to avoid nesting f-strings.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#3
calling it a Frankenstein ... i would agree. but what else is there. i first wrote a function to do it, but that was worse grabbing the caller's namespaces and such. people are going to get used to short code doing f-strings so when they run into a dynamic case, such as reading the format in from a file, they want to do it as close to the same way as they can. i did, too. when i figure it out (was not hard) i decided to share.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#4
The normal format-method does not allow function calls.
The object is still an str, still has the method upper, which
is also visible with dot-access in the string, but a call is not possible.
Before you send your values to the format method, you have to do all calls there or before.
silly = 'crazy'
exs = [
    "hellp {silly} world",
    "hey {silly}, this script is {silly_capital}!",
    "1 + 1 = {result} ... how {silly}!",
    ]
for ex in exs:
    result = ex.format(silly=silly, silly_capital=silly.upper(), result=2)
    print(result)
Or if all information are available:
a = 1
b = 1
x = a + b
silly = 'crazy'
exs = [
    f"hellp {silly} world",
    f"hey {silly}, this script is {silly.upper()}!",
    f"{a} + {b} = {x} ... how {silly}!",
    ]
for ex in exs:
    print(ex)
In the case you have to call this repeating, you can wrap it into a function:
def foo(a, b, silly):
    x = a + b
    exs = [
        f"hellp {silly} world",
        f"hey {silly}, this script is {silly.upper()}!",
        f"{a} + {b} = {x} ... how {silly}!",
        ]
    for ex in exs:
        print(ex)
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#5
in your example, and an apparent requirement for format(), is the need to know which variables will be used. what if the scope of variables that could be used is very large, such as several dozen possible variables, even though the actual strings might only use a few. but the code does not get to know a few.

i see you changed the string literals making up the list to f-strings (literals). i had them as plain old strings for a reason. they served as an example of how a plain old string would be used. what if my example had shown the 3 strings being read from 3 different files? then how would you code that?

the point is: you have a string (type str) with the format in it, just as you would have between quotes in an f-string literal. but this string did not come from an f-string literal. it doesn't matter where it came from. it is type str and contains a format that has not yet been processed. now, it needs to be processed in exactly the same way the source between quotes is processed in an f-string literal. of course, this is a rare need. but, the chance of it is not zero.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#6
In the case where you need to aggregate information, which should result in a formatted string, you could do this in an isolated function. The benefit is, that everything is very close. You see which names are used and you see the format str in the same block.

The 3-File example. The ExitStack is only to save lines of code..
def make_string(file1, file2, file3):
    with contextlib.ExitStack() as stack:
        files = [stack.enter_context(open(f)) for f in (file1, file2, file3)]
        header1 = files[0].readline().strip()
        header2 = files[1].readline().strip()
        header3 = files[2].readline().strip()
    return f"Header1: {header1}\nHeader2: {header2}\nHeader3: {header3}"
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#7
i don't see how "foo: {foo}" in file1 is going to pick up the variable foo from the caller's name spaces.

how can this method result in some simple (one short line) code to replace (only) line 6 of my originally posted code?
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020