简体   繁体   English

python 字符串格式化 - 隐式 str() + 格式说明符

[英]python string formatting - implicit str() + format specifiers

string formatting supports implicit str ifying.字符串格式支持隐式str化。 However, string format specifiers don't appear to be compatible with this, only explicit str objects (regardless of using type= s ).但是,字符串格式说明符似乎与此不兼容,只有显式str对象(无论使用 type= s )。 I cannot find this behavior documented anywhere without pulling up the cpython code.如果不调出 cpython 代码,我在任何地方都找不到这种行为的记录。 default ubuntu 20.04 python3.8 install.默认 ubuntu 20.04 python3.8 安装。 using an explicit str() call is workable but it's not very clean especially in my use case where it now liters the code.使用显式的str()调用是可行的,但它不是很干净,尤其是在我的用例中,它现在会增加代码。

obj = object()
explicit = str(obj)
print(f"{explicit:.5}")
print(f"{obj}")
print(f"{obj:.5}") # TypeError: unsupported format string passed to object.__format__

Question:问题:

  • Have I interpreted this correctly我是否正确解释了这一点
  • where should I be looking to glean this info myself (if exists outside cpython code), and我应该在哪里自己收集这些信息(如果存在于 cpython 代码之外),并且
  • is there any way accomplish format specifiers {:...} while relying on the implicit str() ification?有没有办法在依赖隐式str()化的同时完成格式说明符{:...}

You could either implement the __format__ method in your object class or place the str() directly in the format string:您可以在 object class 中实现 __format__ 方法,也可以将 str() 直接放在格式字符串中:

print(f"{str(obj):.5}")

see PEP 498 for details.有关详细信息,请参阅PEP 498

note that f"{obj:s..5}" also works but, in that same specification, !s and !r are considered redundant and only maintained for backward compatibility请注意, f"{obj:s..5}"也可以工作,但在同一规范中,!s 和 !r 被认为是多余的,仅出于向后兼容性而维护

It works if you explicitly request string conversion:如果您明确请求字符串转换,它会起作用:

>>> print(f"{obj!s:.5}")
<obje

Behind the scenes, I suspect that the result of the expression is not passed to str first, but rather to format :在幕后,我怀疑表达式的结果不是首先传递给str ,而是传递给format

>>> format(obj, "%s")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported format string passed to object.__format__

In this case, object.__format__ itself doesn't automatically do a conversion to string using object.__str__ , for whatever reason.在这种情况下,无论出于何种原因, object.__format__本身都不会使用object.__str__自动转换为字符串。

From the C source来自 C 源

/* Issue 7994: If we're converting to a string, we
   should reject format specifications */

Issue object.问题object。 format should reject format strings argues that the base object from which all other objects are formed should not assume that it is a string-like thing that supports string specifiers.格式应该拒绝格式字符串认为形成所有其他对象的基础 object 不应假定它是支持字符串说明符的类似字符串的东西。 Format specifiers are type specific so the parent of all types can't make any judgement about them.格式说明符是特定于类型的,因此所有类型的父级无法对它们做出任何判断。 It would have to cast itself to one of its subtypes which does have a formatter, but which one?它必须将自己转换为具有格式化程序的子类型之一,但是哪个子类型

An interesting example is a user defined class that doesn't implement a formatter and so uses the default.一个有趣的例子是用户定义的 class 没有实现格式化程序,因此使用默认值。

>>> class Foo:
...     pass
... 
>>> foo = Foo()
>>> f"{foo:.5}"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported format string passed to Foo.__format__

To get your desired result, object.__format__ would have to call foo.__str__().__format__(the_specifier) but that's an odd thing to do.为了得到你想要的结果, object.__format__必须调用foo.__str__().__format__(the_specifier)但这是一件奇怪的事情。 Why should it assume that string formatters are the right thing to apply here?为什么要假设字符串格式化程序在这里应用是正确的? Why not __repr__ instead?为什么不__repr__代替? The object was clear that it don't want no stinking format spec, so don't give it one. object 明确表示它不希望没有臭名昭著的格式规范,所以不要给它一个。

The solution is to provide an explicit string conversion first解决方案是首先提供显式字符串转换

f"{obj!s:.5}"

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM