有多种字符串格式设置方法:

Python<2.6:“您好%s”%namePython 2.6+:“Hello{}”.format(name)(使用str.format)Python 3.6+:f“{name}”(使用f-string)

哪种情况更好?在什么情况下?


以下方法具有相同的结果,那么有什么区别?name=“爱丽丝”“你好%s”%name“您好{0}”.format(名称)f“您好{name}”#使用命名参数:“您好%(kwarg)s”%{'kwarg':name}“你好{kwarg}”.format(kwarg=name)f“您好{name}”字符串格式化何时运行,如何避免运行时性能损失?


如果您试图结束一个重复的问题,该问题只是在寻找一种格式化字符串的方法,请使用How do I put a variable value in a string?。


当前回答

我想补充一下,从3.6版开始,我们可以使用fstring,如下所示

foo = "john"
bar = "smith"
print(f"My name is {foo} {bar}")

这给了

我叫约翰·史密斯

所有内容都转换为字符串

mylist = ["foo", "bar"]
print(f"mylist = {mylist}")

结果:

mylist=['fo','bar']

您可以像其他格式方法一样传递函数

print(f'Hello, here is the date : {time.strftime("%d/%m/%Y")}')

举个例子

您好,这里是日期:2018年4月16日

其他回答

回答第一个问题。格式在许多方面似乎更为复杂。关于%的一个令人讨厌的问题是,它可以接受变量或元组。你会认为以下方法总是有效的:

"Hello %s" % name

然而,如果name恰好是(1,2,3),它将抛出一个TypeError。为了保证它总是打印出来,你需要

"Hello %s" % (name,)   # supply the single argument as a single-item tuple

这太难看了。格式没有这些问题。同样在您给出的第二个示例中,.format示例看起来更简洁。

仅用于向后兼容Python 2.5。


为了回答第二个问题,字符串格式化与任何其他操作同时发生-当计算字符串格式化表达式时。Python不是一种惰性语言,它在调用函数之前会对表达式求值,因此表达式log.debug(“somedebuginfo:%s”%some_info)将首先将字符串求值为,例如“somedebug-info:roflcopters is active”,然后将该字符串传递给log.debug()。

Python 3.6.7比较:

#!/usr/bin/env python
import timeit

def time_it(fn):
    """
    Measure time of execution of a function
    """
    def wrapper(*args, **kwargs):
        t0 = timeit.default_timer()
        fn(*args, **kwargs)
        t1 = timeit.default_timer()
        print("{0:.10f} seconds".format(t1 - t0))
    return wrapper


@time_it
def new_new_format(s):
    print("new_new_format:", f"{s[0]} {s[1]} {s[2]} {s[3]} {s[4]}")


@time_it
def new_format(s):
    print("new_format:", "{0} {1} {2} {3} {4}".format(*s))


@time_it
def old_format(s):
    print("old_format:", "%s %s %s %s %s" % s)


def main():
    samples = (("uno", "dos", "tres", "cuatro", "cinco"), (1,2,3,4,5), (1.1, 2.1, 3.1, 4.1, 5.1), ("uno", 2, 3.14, "cuatro", 5.5),) 
    for s in samples:
        new_new_format(s)
        new_format(s)
        old_format(s)
        print("-----")


if __name__ == '__main__':
    main()

输出:

new_new_format: uno dos tres cuatro cinco
0.0000170280 seconds
new_format: uno dos tres cuatro cinco
0.0000046750 seconds
old_format: uno dos tres cuatro cinco
0.0000034820 seconds
-----
new_new_format: 1 2 3 4 5
0.0000043980 seconds
new_format: 1 2 3 4 5
0.0000062590 seconds
old_format: 1 2 3 4 5
0.0000041730 seconds
-----
new_new_format: 1.1 2.1 3.1 4.1 5.1
0.0000092650 seconds
new_format: 1.1 2.1 3.1 4.1 5.1
0.0000055340 seconds
old_format: 1.1 2.1 3.1 4.1 5.1
0.0000052130 seconds
-----
new_new_format: uno 2 3.14 cuatro 5.5
0.0000053380 seconds
new_format: uno 2 3.14 cuatro 5.5
0.0000047570 seconds
old_format: uno 2 3.14 cuatro 5.5
0.0000045320 seconds
-----

对于python版本>=3.6(参见PEP 498)

s1='albha'
s2='beta'

f'{s1}{s2:>10}'

#output
'albha      beta'

顺便说一句,在日志记录中使用新样式的格式并不一定会影响性能。您可以将任何对象传递给实现__str__魔术方法的logging.debug、logging.info等。当日志模块决定必须发出消息对象(无论是什么)时,它会在发出消息之前调用str(message_object)

import logging


class NewStyleLogMessage(object):
    def __init__(self, message, *args, **kwargs):
        self.message = message
        self.args = args
        self.kwargs = kwargs

    def __str__(self):
        args = (i() if callable(i) else i for i in self.args)
        kwargs = dict((k, v() if callable(v) else v) for k, v in self.kwargs.items())

        return self.message.format(*args, **kwargs)

N = NewStyleLogMessage

# Neither one of these messages are formatted (or calculated) until they're
# needed

# Emits "Lazily formatted log entry: 123 foo" in log
logging.debug(N('Lazily formatted log entry: {0} {keyword}', 123, keyword='foo'))


def expensive_func():
    # Do something that takes a long time...
    return 'foo'

# Emits "Expensive log entry: foo" in log
logging.debug(N('Expensive log entry: {keyword}', keyword=expensive_func))

Python 3文档中对此进行了描述(https://docs.python.org/3/howto/logging-cookbook.html#formatting-样式)。但是,它也可以与Python 2.6一起使用(https://docs.python.org/2.6/library/logging.html#using-作为消息的任意对象)。

使用此技术的一个优点是,它允许延迟值,例如上面的函数expensive_func,而不是格式化样式不可知。这为Python文档中给出的建议提供了一个更优雅的替代方案:https://docs.python.org/2.6/library/logging.html#optimization.

format还有另一个优点(我在答案中没有看到):它可以获取对象财产。

In [12]: class A(object):
   ....:     def __init__(self, x, y):
   ....:         self.x = x
   ....:         self.y = y
   ....:         

In [13]: a = A(2,3)

In [14]: 'x is {0.x}, y is {0.y}'.format(a)
Out[14]: 'x is 2, y is 3'

或者,作为关键字参数:

In [15]: 'x is {a.x}, y is {a.y}'.format(a=a)
Out[15]: 'x is 2, y is 3'

据我所知,%是不可能的。