Capture ** vars () pattern in string formatting

I often use the following pattern to format strings.

a = 3
b = 'foo'
c = dict(mykey='myval')

#prints a is 3, b is foo, mykey is myval
print('a is {a}, b is {b}, mykey is {c[mykey]}'.format(**vars()))

That is, I often have values ​​that I need to print in the local namespace represented by the vars () call. However, when I look through my code, it seems like an awfully unpythonic constantly repeating pattern .format(**vars()).

I would like to create a function that will capture this pattern. It will be something like the following.

# doesn't work
def lfmt(s):
    """
    lfmt (local format) will format the string using variables
    in the caller local namespace.
    """
    return s.format(**vars())

Except that by the time I am in the namespace lfmt, vars () is no longer what I want.

How can I write lfmt so that it executes vars () in the namespace of the callers, so that the following code would work as an example above?

print(lfmt('a is {a}, b is {b}, mykey is {c[mykey]}'))
+3
5

. lfmt , inspect. , , inspect , Python

import inspect
def lfmt(s):
    caller = inspect.currentframe().f_back
    return s.format(**caller.f_locals)

a = 3
b = 'foo'
c = dict(mykey='myval')

print(lfmt('a is {a}, b is {b}, mykey is {c[mykey]}'))
# a is 3, b is foo, mykey is myval
+2

.

:

import inspect
import pprint

def lfmt(s):
    for frame in inspect.getouterframes(inspect.currentframe()):
        f = frame[0]
        print pprint.pformat(f.f_locals)
    return '???'

if __name__ == '__main__':
    a = 10
    b = 20
    c = 30
    lfmt('test')
+1

:

import sys

def lfmt(s):
    """
    lfmt (local format) will format the string using variables
    in the caller local namespace.
    """

    if hasattr(sys, "tracebacklimit") and sys.tracebacklimit == 0:
        raise Exception, "failfailfail"

    try:
        raise ZeroDivisionError
    except ZeroDivisionError:
        f = sys.exc_info()[2].tb_frame.f_back

    return s.format(**f.f_locals)

a = 5
somestring = "text"
print lfmt("{a} {somestring}")

, , , . , " ", "XXX fix me XXX".

0

,vars , ?

def lfmt(s,v):
    """
    lfmt (local format) will format the string using variables
    from the dict returned by calling v()"""
    return s.format(**v())

print(lfmt('a is {a}, b is {b}, mykey is {c[mykey]}',vars))
0

You can also use sysinstead inspect, but I don't know if it has the same problem with different implementations as inspect.

import sys

def lfmt(s):
    caller = sys._getframe(1)
    return s.format(**caller.f_locals)

This is until I got it: Python interpolation implementation

0
source

Source: https://habr.com/ru/post/1731429/


All Articles