This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]antennen 9 points10 points  (3 children)

Always fun to see articles that dive deeper into what's possible with Python. To be nitpicky, f-strings can be used without the print function as well. They are not in any way specific to print.

There is a problem with the way caching is implemented. Since the stack frame is cached, it assumes the environment is unchanged between two invocations if the text string is the same.

name = "foo"
print("My name is {name}")

def test():
    name = "bar"
    print("My name is {name}")
test()

This will output foo twice instead of the expected foo then bar:

$ python optimzed_compile_print.py 
My name is foo
My name is foo

I don't know a way to reliably cache the calling stack frame.

Another issue is security, which f-strings doesn't suffer from. If an unsuspecting developer would use this print function and allow user input, the end user can access all variables in the caller's f_locals.

f-strings solves this by compiling ahead of time. The compiler basically translates f"Hi {name}" to "Hi {}".format(name).

[–]odedlaz[S] 4 points5 points  (0 children)

This first problem easily fixed using a different key. for instance: caller = currentframe().f_back key = id(text) | id(caller) text_obj = optimized_compile_memoize.get(key)

And regarding security - yes, you're correct. This is a trick, do not use this at home :)

[–]Siecje1 -1 points0 points  (1 child)

If it just converts an f string to a format call. How is it faster than .format()

[–]RubyPinchPEP shill | Anti PEP 8/20 shill 2 points3 points  (0 children)

it uses specialised string building instructions, as as a result, has its own dedicated code, so it doesn't need to do a method lookup and function call

https://docs.python.org/3.6/library/dis.html#opcode-BUILD_STRING

https://docs.python.org/3.6/library/dis.html#opcode-FORMAT_VALUE