Python 字符串格式选项:优缺点

Python 字符串格式选项:优缺点,python,string-formatting,Python,String Formatting,这是Python中格式化字符串的两种非常流行的方法。一个是使用命令: >>> 'I will be %(years)i on %(month)s %(day)i' % {'years': 21, 'month': 'January', 'day': 23} 'I will be 21 on January 23' 另一个使用简单的元组: >>> 'I will be %i on %s %i' % (21, 'January', 23) 'I will be

这是Python中格式化字符串的两种非常流行的方法。一个是使用
命令

>>> 'I will be %(years)i on %(month)s %(day)i' % {'years': 21, 'month': 'January', 'day': 23}
'I will be 21 on January 23'
另一个使用简单的
元组

>>> 'I will be %i on %s %i' % (21, 'January', 23)
'I will be 21 on January 23'
第一个更可读,但第二个写得更快。事实上,我是在模糊地使用它们


每种方法的优缺点是什么?关于性能、可读性、代码优化(其中一个是否转换为另一个?)以及您认为有助于分享的任何其他内容。

我并不是确切地回答您的问题,但我认为将
格式
加入您的组合会很好

我个人更喜欢
格式的语法,而不是两者:

'I will be {years} on {month} {day}'.format(years=19, month='January', day=23)
如果我想要紧凑的东西,我只写:

'I will be {} on {} {}'.format(19, 'January', 23)
而且
format
可以很好地处理对象:

class Birthday:
  def __init__(self, age, month, day):
    self.age = age
    self.month = month
    self.day = day

print 'I will be {b.age} on {b.month} {b.day}'.format(b = Birthday(19, 'January', 23))
为什么
format()
%
字符串操作更灵活 我认为你真的应该坚持使用
str
format()
方法,因为它是格式化字符串的首选方法,将来可能会取代字符串格式化操作

此外,它还有一些非常好的功能,可以将基于位置的格式设置与基于关键字的格式设置结合起来:

>>> string = 'I will be {} years and {} months on {month} {day}'
>>> some_date = {'month': 'January', 'day': '1st'}
>>> diff = [3, 11] # years, months
>>> string.format(*diff, **some_date)
'I will be 3 years and 11 months on January 1st'
>>> name = 'John'
>>> surname = 'Smith'
>>> age = 87
# some code goes here
>>> 'My name is %(surname)s, %(name)s %(surname)s. I am %(age)i.' % locals()
'My name is Smith, John Smith. I am 87.'
即使是以下措施也会奏效:

>>> string = 'On {month} {day} it will be {1} months, {0} years'
>>> string.format(*diff, **some_date)
'On January 1st it will be 11 months, 3 years'
还有一个原因支持
format()
。因为它是一个方法,所以可以像下面的示例中那样作为回调传递:

>>> data = [(1, 2), ('a', 'b'), (5, 'ABC')]
>>> formatter = 'First is "{0[0]}", then comes "{0[1]}"'.format
>>> for item in map(formatter, data):
    print item


First is "1", then comes "2"
First is "a", then comes "b"
First is "5", then comes "ABC"
它不是比字符串格式化操作灵活得多吗

有关
%
操作和
.format()
方法之间的比较,请参阅上的更多示例

比较基于元组的
%
字符串格式与基于字典的格式 通常有三种调用
%
字符串操作的方法(是的,三种,而不是两种):

base_string % values
>>> 'My name is {surname}, {name} {surname}. I am {age}.'.format(**locals())
'My name is Smith, John Smith. I am 87.'
它们因
值的类型不同而不同(这是
基本字符串
内容的结果):

  • 它可以是一个
    元组
    ,然后按照它们在元组中出现的顺序逐个替换

    >>> 'Three first values are: %f, %f and %f' % (3.14, 2.71, 1)
    'Three first values are: 3.140000, 2.710000 and 1.000000'
    
  • 它可以是一个
    dict
    (字典),然后根据关键字替换它们

    >>> 'My name is %(name)s, I am %(age)s years old' % {'name':'John','age':98}
    'My name is John, I am 98 years old'
    
  • 如果
    base\u字符串
    包含应插入值的单个位置,则它可以是单个值:

    >>> 'This is a string: %s' % 'abc'
    'This is a string: abc'
    
它们之间有明显的区别,并且这些方法不能组合(与上面提到的能够组合某些功能的
format()
method相反)

但是,有一些东西只适用于基于字典的字符串格式化操作,而在其余三种格式化操作类型中是不可用的。这是一种以简单的方式用实际变量名替换说明符的能力:

>>> string = 'I will be {} years and {} months on {month} {day}'
>>> some_date = {'month': 'January', 'day': '1st'}
>>> diff = [3, 11] # years, months
>>> string.format(*diff, **some_date)
'I will be 3 years and 11 months on January 1st'
>>> name = 'John'
>>> surname = 'Smith'
>>> age = 87
# some code goes here
>>> 'My name is %(surname)s, %(name)s %(surname)s. I am %(age)i.' % locals()
'My name is Smith, John Smith. I am 87.'
记录在案:当然,通过使用
format()
,通过如下方式解包字典,可以轻松替换上述内容:

base_string % values
>>> 'My name is {surname}, {name} {surname}. I am {age}.'.format(**locals())
'My name is Smith, John Smith. I am 87.'

其他人知道什么是特定于一种类型的字符串格式化操作的功能,而不是其他类型的吗?听到这个消息可能会很有趣。

我不是在回答这个问题,而是在解释我在报告中提出的想法

我介绍了所谓的“stringizer”函数:任何名称以“$”开头的函数都是stringizer。编译器将“$name('and')”视为字符串文字加上函数调用的引号

例如:

$print(I will be {b.age} on {b.month} {b.day});
实际上是编译成

$print("I will be ", b.age, " on ",b.month," ",b.day);
其中偶数参数总是文字字符串,奇数参数是表达式。通过这种方式,可以定义使用不同格式/参数处理的自定义字符串

例如
Element.$html(Hello{who})将对表达式应用HTML转义。以及这个
元素。$(选项[value={12}])将以jQuery样式进行选择

非常方便和灵活


我不确定在Python中不改变编译器就可以做这样的事情。把它当作一个想法来考虑。 好问题。我个人觉得第二个更具可读性。代码可读性依赖于大脑。另一方面,不知何故,大括号总是会毁了我的工作。当使用
format()
方法时,您不需要在这两种传递参数的方法之间进行选择-您可以同时使用这两种方法(参见我的答案)。+1关于对象的优点。我也更喜欢
format()
。我以某种方式扩展了您的答案,展示了如何使用
format()
将两种格式化方式(如OP所述)组合成单个调用的示例。这两种答案都很好,我对
format()
知之甚少。但是,有关于
%
格式的信息吗?(这就是要点)
.format()
太棒了。我不知道
*diff
扩展,所以谢谢你的提示;)两个答案都很好,我对
format()
不太了解。但是,有关于
%
格式的信息吗?(这就是要点)@julio.alegria:我已经用一个例子更新了我的答案,说明了如何使用基于字典的字符串操作——这种方法非常有用,而且不容易被基于元组的操作所取代。
locals()
!天才!我也不知道。我想到的
%
format()
没有的一个功能是“转换”(我不确定这是否是正确的名称),例如:
%2.6f
。。有时候真的很有用。@julio.alegria:谢谢!说到“转换”,我相信您是在谈论(来自M.Lutz的“Learning Python.4th Edition”):“浮点数在格式化方法调用中支持与%表达式中相同的类型代码和格式化特性。”。换句话说,例如
'%2.6f'%.123456789123
'{:2.6f}'。格式(.123456789123)
为您提供
'0.123457'
。因此,基本上,
format()