如何在字符串格式化期间使用分配给变量的值?

时间:2014-03-15 09:31:14

标签: python string string-formatting

这样可行:

>>> x = 1
>>> y = 2
>>> "a={a}, b={b}, a+b={c}".format( a=x, b=y, c=x+y )

'a=1, b=2, a+b=3'

但这并不是:

>>> "a={a}, b={b}, a+b={c}".format( a=x, b=y, c=a+b )

NameError: name 'a' is not defined

有没有办法让第二个工作? (比如说xy是函数调用,我不想在字符串格式化过程中重新计算它们。

3 个答案:

答案 0 :(得分:3)

对于此,最pythonic(在这种情况下是可读的)解决方案不是使用lambda函数,而是在a调用之前缓存bformat()

a = function_x()
b = function_y()
"a={a}, b={b}, a+b={c}".format(a=a, b=b, c=a+b)

从现在起6个月后查看代码,你会感激不尽。

答案 1 :(得分:1)

您可以使用lambda

执行此操作
def x():
    return 1

def y():
    return 2

>>> "a={a},b={b}, a+b={c}".format(**(lambda a=x(),b=y():{'a':a,'b':b,'c':a+b})())
'a=1,b=2, a+b=3'

这个lambda表达式等于调用预定义函数:

def twosumm(a, b):
    return {'a':a, 'b':b, 'c': a+b}

>>> "a={a},b={b}, a+b={c}".format(**twosumm(x(), y()))
'a=1,b=2, a+b=3'

我还认为最好使用简单易读的解决方案,只需致电x()y()即可在形成之前获得结果:

>>> a, b = x(), y()
>>> "a={a},b={b}, a+b={c}".format(a=a, b=b, c=a+b)
'a=1,b=2, a+b=3'

答案 2 :(得分:0)

x = 1
y = 2

def f(x,y):
    return (x,y,x+y)

print "a={}, b={}, a+b={}".format( *f(x,y) )
# or
print "a={0[0]}, b={0[1]}, a+b={0[2]}".format( f(x,y) )

修改

我认为你的问题写错了,导致对它的理解模糊,然后是错误的答案。

xy不是函数调用。如它们所示,它们只是标识符

如果你唤起函数调用,我认为这是因为,事实上,你希望获得类似的结果:
    "a={a}, b={b}, a+b={c}".format( a=f(), b=g(), c=f()+g() )
但无需编写c=f()+g(),因为它意味着f()g()分别执行了两次。

首先,在Python中永远不可能写出.format( a=x, b=y, c=a+b ).format( a=f(), b=g(), c=a+b )之类的内容,其中ab中的c=a+b将引用相同的内容ab中的a=xb=y对象 因为=左侧的任何标识符都位于format()的本地名称空间中,而=右侧的任何标识符都位于函数format()之外的名称空间中。
顺便说一下,这就是为什么左边的标识符被称为参数,右边的标识符是作为参数传递的对象的标识符。

其次,如果你想避免两次写f()(一次作为单独的参数,一次在表达式f()+g()中),而g()则相同,这意味着你只想写一次,就像单独的论点一样 所以,如果我理解你,你基本上希望写出类似的东西:
"a={a}, b={b}, a+b={}".format( a=f(), b=g() )
使用当前方法str.format,具有三个替换字段{}的此表达式显然不正确。

无论如何,让我们重新定义方法format!然后,只能将两个参数传递给format()

def fx(): return 101
def fy(): return 45

class Pat(str):
    def __init__(self,s):
        self = s
    def format(self,x,y):
        return str.format(self,x,y,x+y)

p = Pat("a={}, b={}, a+b={}")
print 'p==',p
print p.format(fx(),fy())

结果

p : a={}, b={}, a+b={}
a=101, b=45, a+b=146

我们甚至可以做更复杂的事情:

from sys import exit

import re
def fx(): return 333
def fy(): return 6

class Pat(str):
    def __init__(self,s):
        for x in re.findall('(?<=\{)[^}]+(?=\})',s):
            if x not in ('A','M'):
                mess = " The replacement field {%s] isn't recognised" % x
                exit(mess)
        self.orig = s
        self.mod = re.sub('\{[^}]*\}','{}',s)
    def modif(self,R):
        it = iter(R)
        return tuple(sum(R) if x=='{A}'
                     else reduce(lambda a,b: a*b, R) if x=='{M}'
                     else next(it)
                     for x in re.findall('(\{[^}]*\})',self))
    def format(self,*args):
        return ''.join(self.mod.format(*self.modif(args)))

print Pat("a={}, b={}, a+b={A}").format(fx(),fy())
print '******************************************'
print Pat("a={}, b={}, c={}, a+b+c={A}").format(fx(),fy(),5000)
print '******************************************'
print Pat("a={}, b={}, a*b={M}").format(fx(),fy())
print '******************************************'
print Pat("a={}, b={}, axb={X}").format(fx(),fy())

结果

a=333, b=6, a+b=339
******************************************
a=333, b=6, c=5000, a+b+c=5339
******************************************
a=333, b=6, a*b=1998
******************************************

Traceback (most recent call last):
  File "I:\potoh\ProvPy\Copie de nb.py", line 70, in <module>
    print Pat("a={}, b={}, axb={X}").format(fx(),fy())
  File "I:\potoh\ProvPy\Copie de nb.py", line 51, in __init__
    exit(mess)
SystemExit:  The replacement field {X] isn't recognised