Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
149 views
in Technique[技术] by (71.8m points)

python - Why does adding formatting information to a f-string with tuple values raise a TypeError?

I'm trying to understand the following behavior of f-strings in Python:

The following line in which the tuple value is converted explicitly via str() works fine.

f"{str((1,2,3)):>10}"

However if I drop the explicit conversion the line raises a TypeError: unsupported format string passed to tuple.__format__:

f"{(1,2,3):>20}"

There are no issues when there isn't any formatting given:

f"{(1,2,3)}"

I had expected that the f-string converts the tuple into a string automagically and then enforces the formatting requirements. This does not seem to be the case. Can somebody explain? Is there another workaround other then the explicit conversion via str()?

question from:https://stackoverflow.com/questions/65861574/why-does-adding-formatting-information-to-a-f-string-with-tuple-values-raise-a-t

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As you experienced, there is some magic going on. However, it is not that every item is just being converted to string before formatting.

The TypeError explains what Python is trying to do: It is trying to call the __format__ method of your tuple. But it fails because tuple.__format__ does not expect a > argument. If you were to fine-tune the formatting of your own class, you could do something like this:

class MyType:
    def __init__(self, value):
        self.value = value

    def __format__(self, format_spec):
        return f"this is the value {self.value} formatted against {format_spec}"


if __name__ == '__main__':
    d = MyType(6)

    print(f"{d:>10}")

Output:

this is the value 6 formatted against >10

So it would be up to your own MyType.__format__ to generate and return a string according to the format_spec.

One native Python type that has a __format__ method that deals with a format_spec like >10 would be the string class. That is the reason f"{str((1,2,3)):>10}" works.

What you could do instead would be to use the ! marker to convert the tuple to string - this is equivalent to using str() but less verbose:

f"{(1,2,3)!s:>10}"

Output: ' (1, 2, 3)'

With one space added to the left as wanted.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...