Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从其调用范围中提取变量的字符串格式化程序是一种糟糕的做法吗?_Python - Fatal编程技术网

Python 从其调用范围中提取变量的字符串格式化程序是一种糟糕的做法吗?

Python 从其调用范围中提取变量的字符串格式化程序是一种糟糕的做法吗?,python,Python,我有一些代码可以进行大量的字符串格式化,通常,我最终的代码是: "...".format(x=x, y=y, z=z, foo=foo, ...) 我试图将大量变量插入到一个大字符串中 是否有充分的理由不编写这样一个函数,它使用inspect模块查找要插值的变量 import inspect def interpolate(s): return s.format(**inspect.currentframe().f_back.f_locals) def generateTheStr

我有一些代码可以进行大量的字符串格式化,通常,我最终的代码是:

"...".format(x=x, y=y, z=z, foo=foo, ...)
我试图将大量变量插入到一个大字符串中

是否有充分的理由不编写这样一个函数,它使用
inspect
模块查找要插值的变量

import inspect

def interpolate(s):
    return s.format(**inspect.currentframe().f_back.f_locals)

def generateTheString(x):
    y = foo(x)
    z = x + y
    # more calculations go here
    return interpolate("{x}, {y}, {z}")

下面的代码是一种更简单、更安全的方法。inspect.currentframe并非在所有python实现上都可用,因此当代码不可用时,它会中断。在jython、ironpython或pypy下,它可能不可用,因为它似乎是一个cpython的东西。这会降低代码的可移植性

print "{x}, {y}".format(**vars())
这项技术实际上在

这也可以通过将表作为关键字参数传递给 “**”符号。这在与 新的内置vars()函数,返回包含 所有局部变量

同样在python文档中

CPython实现细节:此函数依赖于Python堆栈 解释器中的帧支持,不能保证在 Python的所有实现。如果在没有 Python堆栈框架支持此函数不返回任何值


inspect
模块中,
currentframe
的定义如下:

if hasattr(sys, '_getframe'):
    currentframe = sys._getframe
else:
    currentframe = lambda _=None: None
因此,除非
sys
具有
\u getframe
属性,否则
interpolate
函数将无法工作

对于
sys.\u getframe
说:

CPython实现细节:此函数应用于 仅供内部和专门用途。它不一定存在 在Python的所有实现中


书写

"{x}, {y}, {z}".format(**vars())
在函数体中的长度不比

interpolate("{x}, {y}, {z}")

您的代码将更易于移植。

好的老邮递员有一个功能,它可以完成以下任务:

print "{x}, {y}".format(**vars())
def _(s):
    if s == '':
        return s
    assert s
    # Do translation of the given string into the current language, and do
    # Ping-string interpolation into the resulting string.
    #
    # This lets you write something like:
    #
    #     now = time.ctime(time.time())
    #     print _('The current time is: %(now)s')
    #
    # and have it Just Work.  Note that the lookup order for keys in the
    # original string is 1) locals dictionary, 2) globals dictionary.
    #
    # First, get the frame of the caller
    frame = sys._getframe(1)
    # A `safe' dictionary is used so we won't get an exception if there's a
    # missing key in the dictionary.
    dict = SafeDict(frame.f_globals.copy())
    dict.update(frame.f_locals)
    # Translate the string, then interpolate into it.
    return _translation.gettext(s) % dict

因此,如果巴里·华沙能够做到这一点,我们为什么不能呢?

更新:Python 3.6内置了以下功能(一个更强大的变体):

x, y, z = range(3)
print(f"{x} {y + z}")
# -> 0 3


它[手动解决方案]导致嵌套函数出现一些令人惊讶的行为:

from callerscope import format

def outer():
    def inner():
        nonlocal a
        try:
            print(format("{a} {b}"))
        except KeyError as e:
            assert e.args[0] == 'b'
        else:
            assert 0

    def inner_read_b():
        nonlocal a
        print(b) # read `b` from outer()
        try:
            print(format("{a} {b}"))
        except KeyError as e:
            assert 0
    a, b = "ab"
    inner()
    inner_read_b()
注意:同一调用的成功或失败取决于变量是在其上面还是下面提到的

其中,
callerscope
是:

import inspect
from collections import ChainMap
from string import Formatter

def format(format_string, *args, _format=Formatter().vformat, **kwargs):
    caller_locals = inspect.currentframe().f_back.f_locals
    return _format(format_string, args, ChainMap(kwargs, caller_locals))

你也可以只使用
locals()
globals()
@F.C.:的确,但是让
interpolate(“…”,**locals())
到处乱七八糟,加上在
s
是局部变量的罕见情况下它会失败,因为它会尝试将第一个参数设置两次,大概你是手工输入的。为什么不在定义函数时简单地将它们放在字典中呢?我认为它看起来很棒。我不通过PyPy使用python,这段代码会非常慢。这将是您自己的错误(在生产中使用调试挂钩)。