简体   繁体   English

使用!s vs.:s在Python中格式化字符串

[英]Using !s vs. :s to format a string in Python

I'm really curious about :s format string in Python 3. The documentation says !s is conversion and that :s is format_spec . 我真的很好奇:s Python 3中:s格式字符串。 文档!s转换 ,并且:sformat_spec

It also says !s will apply str() , but it doesn't say anything similar about :s . 它还说!s将应用str() ,但它没有说类似的东西:s I think there's no significant difference between them, but I want to be sure. 我认为它们之间没有显着差异,但我想确定。 Can anyone clarify these? 谁能澄清这些?

Some code example: 一些代码示例:

print("{!s}".format("this"))
print("{:s}".format("that"))
# I want to be sure that these two are processed identically internally

It's still confusing, but let me wrap up with my own (layperson's) words. 它仍然令人困惑,但让我用自己的(layperson)的话来结束。

  1. type("whatever".format) is always str . type("whatever".format)总是str
  2. Use !s if you want convert the object into str before formatting. 如果要在格式化之前将对象转换为str ,请使用!s
  3. :s means that the object(or the converted object) will be treated as str during some internal formatting process. :s表示在某些内部格式化过程中,对象(或转换的对象)将被视为str It's the default format_spec . 这是默认的format_spec

Is anything wrong here? 这里有什么不对吗?

!s , and its brethren !a and !r apply str() , ascii() and repr() respectively before interpolation and formatting. !s和它的兄弟!a!r 插值和格式化之前分别应用str()ascii()repr() These are called conversion flags , and are part of the Format String Syntax spec , not the per-field formatting spec applied to values when interpolating: 这些称为转换标志 ,是格式字符串语法规范的一部分 ,而不是插值时应用于值的每字段格式规范

The conversion field causes a type coercion before formatting . 转换字段在格式化之前导致类型强制。 Normally, the job of formatting a value is done by the __format__() method of the value itself. 通常,格式化值的工作由值本身的__format__()方法完成。 However, in some cases it is desirable to force a type to be formatted as a string, overriding its own definition of formatting. 但是,在某些情况下,最好强制将类型格式化为字符串,从而覆盖其自己的格式定义。 By converting the value to a string before calling __format__() , the normal formatting logic is bypassed. 通过在调用__format__()之前将值转换为字符串,可以绕过普通的格式化逻辑。

Bold emphasis mine. 大胆强调我的。

:s only applies afterwards to the conversion result (or the original object if no conversion had been applied), and only if the __format__ method for the type of object supports that formatting option. :s仅在之后应用于转换结果(如果未应用转换,则仅适用于原始对象),并且仅当对象类型的__format__方法支持该格式化选项时才应用。 Usually, only objects of type str support this formatter; 通常,只有str类型的对象支持此格式化程序; it's there as the default, mostly because the Format Specification Mini-Language allows for the existence of a type character and because the older % printf -style formatting had a %s format. 它是默认设置,主要是因为格式规范迷你语言允许存在类型字符,并且因为较旧的% printf style格式具有%s格式。 If you tried to apply the s type to an object that doesn't support it, you'd get an exception. 如果您尝试将s类型应用于不支持它的对象,则会出现异常。

Use !s (or !a or !r ) when you have an object that is not itself a string and either doesn't support formatting otherwise (not all types do) or would format differently from their str() , ascii() or repr() conversions: 当你有一个本身不是字符串的对象时,请使用!s (或!a!r ),否则不支持格式化(不是所有类型都有)或格式不同于str()ascii()repr()转换:

>>> class Foo:
...     def __str__(self):
...         return "Foo as a string"
...     def __repr__(self):
...         return "<Foo as repr, with åéæ some non-ASCII>"
...     def __format__(self, spec):
...         return "Foo formatted to {!r} spec".format(spec)
...
>>> print("""\
... Different conversions applied:
... !s: {0!s:>60s}
... !r: {0!r:>60s}
... !a: {0!a:>60s}
... No conversions: {0:>50s}
... """.format(Foo()))
Different conversions applied:
!s:                                    Foo as a string
!r:             <Foo as repr, with åéæ some non-ASCII>
!a:    <Foo as repr, with \xe5\xe9\xe6 some non-ASCII>
No conversions: Foo formatted to '>50s' spec

Note: all formatting specified by the format spec are the responsibility of the __format__ method; 注意:格式规范指定的所有格式都是__format__方法的责任; the last line does not apply the alignment operation in the >50s formatting spec, the Foo.__format__ method only used it as literal text in a formatting operation (using a !r conversion here). 最后一行不适用于>50s格式规范中的对齐操作, Foo.__format__方法仅在格式化操作中使用它作为文字文本(在此处使用!r转换)。

For the converted values, on the other hand, the str.__format__ method is used and the output is aligned to the right in a 50 character wide field, padded with spaces on the left. 另一方面,对于转换后的值,使用str.__format__方法,输出在50字符宽的字段中右对齐,在左侧填充空格。

You're unlucky you used strings as the value to be formatted. 你不幸的是你使用字符串作为要格式化的值。 Using pretty much any other object you'd get how these aren't the same. 使用几乎任何其他对象,你会得到这些不一样的东西。

In (as much as I can) layman's terms: 在(尽我所能)外行人的条款:

  • The absence or existence of the conversion flag specifies the type of the value we going to format and, by extent, who's __format__ we'll be calling. 转换标志的缺失或存在指定了我们要格式化的值的类型,并且根据范围,我们将调用谁是__format__ As Martjin points out, by using this we can bypass certain behavior and treat the value more generically (like a string). 正如Martjin指出的那样,通过使用它,我们可以绕过某些行为并更一般地处理该值(如字符串)。 It comes in three different flavors that correspond to the three different ways an object can choose to represent itself as a string. 它有三种不同的风格,对应于对象可以选择将其自身表示为字符串的三种不同方式。
  • The type specifier, coupled with other specifiers, specifies how the type we have should finally be presented . 类型说明符与其他说明符一起指定了最终应该如何呈现我们的类型 For strings there isn't a rich set of options (a string is presented as is) but, for types like int s, you can have different presentations. 对于字符串,没有丰富的选项集(字符串按原样显示)但是,对于类似int的类型,您可以使用不同的演示文稿。

I do think, though, that type is probably a confusing name to give this specifier. 我确实认为,这种type可能是一个令人困惑的名称来给这个说明符。

From the documentation, Python String Formatting : 从文档中, Python字符串格式

The field_name is optionally followed by a conversion field, which is preceded by an exclamation point '!', and a format_spec, which is preceded by a colon ':'. field_name后面跟一个转换字段,前面有一个感叹号'!'和一个format_spec,前面有冒号':'。

So no, it's not the same. 所以不,它不一样。

For example: 例如:

If you want to print a float as a string, you need a conversion (float → string). 如果要将float打印为字符串,则需要转换(float→string)。

"{!s}".format(2.1457)
>>> 2.1457
type("{!s}".format(2.1457))
>>> <type 'str'>

If you don't use the conversion mark, you will get an error. 如果您不使用转换标记,则会出现错误。

"{:s}".format(2.1457)
>>> ValueError: Unknown format code 's' for object of type 'float'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 python 的 eval() 与 ast.literal_eval() - Using python's eval() vs. ast.literal_eval() 在python的string.format()中使用数组 - Using arrays with python's string.format() 使用 &#39;.format()&#39; vs. &#39;%s&#39; 在 cursor.execute() 中用于 mysql JSON 字段,使用 Python mysql.connector, - Use of '.format()' vs. '%s' in cursor.execute() for mysql JSON field, with Python mysql.connector, Python 2.7:%字符串格式与在字符串外部调用变量? - Python 2.7: % string format vs. calling variable outside string? Python 的总和与 NumPy 的 numpy.sum - Python's sum vs. NumPy's numpy.sum Python 3:使用%s和.format() - Python 3: using %s and .format() Python 的字符串连接与 str.join 相比有多慢? - How slow is Python's string concatenation vs. str.join? 以二进制格式显示一串由 1 和 0 组成的字符串 Python - Display a string of 1's and 0's in binary format Python 在Python中,使用“ elif”语句与“ or”语句有什么区别? - In Python what's the difference between using 'elif' statements vs. 'or' statements? 如何强制 Python 的 file.write() 在 Windows 中使用与 Linux 中相同的换行符格式(“\\r\\n”与“\\n”)? - How can I force Python's file.write() to use the same newline format in Windows as in Linux (“\r\n” vs. “\n”)?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM