%-style formatting method

Yes, please. I would fully support this.

I personally will want to use %-placeholders for a very long time (til the day I die, perhaps?!), no matter what anyone else says - but I will be the first to say I never liked the %-operator.

Introducing the str.pformat() method, and immediately updating docs exactly as you suggest, would certainly make me happy, and in the long term it might even allow for str.__mod__ to be outright removed, solving the original problem raised in Deprecate str % format operator.

It does solve the “single tuple argument” problem, but putting together what has already been expressed in several separate posts above:

  • it has to be added to everyone’s codebase;
  • it’s inconsistent with str.format being a method; and
  • it doesn’t provide a nice clear visual separator between format-string and args.

IMO the last reason here is why I don’t already use this solution. I’d prefer str.pformat over str.__mod__, but I’d prefer sticking with str.__mod__ over adding this function everywhere.

1 Like

I’d like to add the footgun of using "Bad value: %s" % value when value can be a tuple or a dict to your list. Not everyone knew this even earlier when %-formatting was all we had, but nowadays when users are more familiar with f-strings, they are even more unlikely to know about it. Thus if they ever need to use %-formatting or maintain code using it, they may introduce an annoying bug that happens only in some cases. str.pformat would avoid that altogether.

3 Likes

Disadvantages:

  • It makes an unnecessary judgement on how people choose to write their code.
  • It increases the likelihood of people “helpfully” submitting issues or PRs to projects to “fix” their use of % formatting.
  • It increases pressure on linters to warn on use of % formatting, which will require users who use % formatting to then disable those warnings.
2 Likes

I believe this is the key point. I question the “unnecessary”. Giving clear directions is helpful. And in cases when one of the options (the %-operator) is clearly inferior, the language should be opinionated. The dance with “old format”/“people don’t use it anymore”, but OTOH “we don’t want to state you shouldn’t use it” is leaving the user in alone. I believe we can and should recommend here.

  • It increases the likelihood of people “helpfully” submitting issues or PRs to projects to “fix” their use of % formatting.

As someone who has seen through thousands of PRs, I claim this is negligible. Either I don’t want to change my codebase, in which the PR is closed in 30s. Or I actually decide the migration is worth it, and then I’m happy that someone puts in the PR.

5 Likes

As someone who has also seen through thousands of PRs, I claim that it is not. If you don’t want to change the codebase, you have to explain why, all because of the completely unnecessary judgement on perfectly valid code. And there’ll be another “helpful” issue posted before long, and you have to explain why all over again. OTOH, if you do accept the change, you now have to test it, make sure it didn’t introduce any bugs, etc, etc, etc. This has a much higher cost than people give it credit for. Churn is expensive.

2 Likes

There’s a difference between “judgement” and “direction”. Saying that % formatting is the old style and people don’t use it any more unless they have a particular need (typically compatibility with other languages/environments) provides direction without making a judgement. Saying “you shouldn’t use it” is a judgement, and puts pressure on people who do use % formatting to “justify” themselves. No-one asks you to justify using i += 1 over i = i + 1 - it’s a style choice between two language features. Why can’t % formatting and f-strings be the same?

The value and popularity of f-strings is pretty obvious from even a cursory glance at modern Python code. Anyone who claims to be confused as to which style to use either hasn’t done much research, or is looking for an argument, IMO.

3 Likes

According to PEP 3103, format was intended as a replacement (not a supplementary form) for the existing ‘%’ string formatting operator.

Whether you want to accept that in your own code is, of course, up to you.

Yes, it is a personal choice whether we conservatively hang on to anachronism, or whether we liberally embrace prevailing trends.

In your comment, you mentioned that you do have a justification when you said “if you have a particular need”. I understand that you may not want to express that need to readers, but ultimately, code exists for readers.

In general where there is a prevalent way of doing something, doing it another way should ideally be justified for the benefit of readers. If you write: x = x + 1 instead of x += 1, a comment explaining why you want to avoid mutating the original x would help the reader.

At this point, using %-formatting is an odd choice, doing x = x + 1 is an odd choice, using 1 to represent True is an odd choice. You can do whatever you like in your own code, but it would help to comment odd choices for the benefit of your readers—if you care about them.

1 Like

Maybe because % is the only string formatting method supported by many programming languages, unlike the newer formatting styles that have become trendy recently:
Python (f""), Ruby (#{}), Swift (\()), JavaScript (Hello, ${name})

When porting legacy code or working across multiple environments, % formatting can be a lifesaver.

Maybe that used to be true? But after you’ve done your porting, then why not run your code through Ruff or AI and convert all of the %-formatting calls to format calls?

PEPs are historical documents capturing the goals of their authors at the time they were written. As a historical statement, what you have said is correct. Unless you can find evidence to support it, though, you can’t claim that it is now intended as a replacement. Percent formatting isn’t supplanted, it is supplemented.

1 Like

Discussion looped back to deprecation. There is no pont in supplying % formatting function, if str % operator isn’t deprecated. Assuming it will be, it is no longer a style choice, and judgement is implied.

I need to support them in multiple languages, so dealing with several string formatting styles would get cumbersome. I only test them in Python, or through Python bindings, and it works perfectly!

1 Like

The reader should understand that the code likely uses % formatting because it is old code but that does not mean that it needs to be updated. It is not necessary to add comments to the old code and the code is generally not improved by being “updated”.

The most likely way that the old code gets significantly improved is if it gets completely replaced at some point in the future. In the mean time PRs from people running ruff because their editor marks some code as red are tedious.

2 Likes

Folks, this proposal is trying to walk a delicate middle ground between “let’s not change anything at all” and “let’s deprecate the %-operator”. The discussion falls of both sides.

I believe this:

  1. We cannot deprecate %-operator for the forseeable future, because it is too much in use.
  2. The %-operator is quirky and error prone.

The middle ground is to give people an alternative that is safe and easy to migrate to.

  • Re: deprecating the %-operator: Before we could talk about this, usage in existing code has to be reduced significantly. Discouraging new use and offering a good alternative will reduce usage longterm and may make the argument easier - it’s probably still 10 years plus before we can have that discussion.
  • Re: Convert everything to {}: That is asked too much. Some people want the %-placeholder notation. But I claim nobody clings to the %-operator. Getting people to change the operator for a method call and keeping the string with %-placeholders is a significantly lower barrier than switching to {} placeholders.
  • Re: Let’s do nothing: Really why? The proposed language addition is minimal, and there is no brealking behavior. This feels like we want to freeze the language as is and not do any improvements - I have yet to hear that somebody wants the %-operator. It’s an awkward remainder from former times and should be put out of sight as much as possible.
5 Likes

The default is “do nothing” because it’s the least work[1]. The fact that it’s a very small addition has to be weighed against the fact that it’s a very small improvement. As you said, the % operator isn’t going away, so that’s not a point in the proposal’s favor.

It’s silly to pretend this means the language is “frozen”–there have been numerous major changes in the past few releases. The GIL is in the process of removal! This tiny change might not be worth the effort, but the language is improving in vastly more consequential ways.


  1. excepting this thread ↩︎

…? I’m confused. Deprecation isn’t removal.

  • First something is marked as deprecated.
  • Then, the usage is reduced.
  • After that, it is removed, not deprecated.

Why discarage something, without deprecating it? Isn’t reduce of usage the only point of deprecation?

Deprecation is a very specific signal that says “this will be removed in the future”, often at a specified future date. If the feature is not planned for removal, it should not be documented as deprecation.

1 Like

Sure, but I wasn’t talking about old code, or what kinds of PRs should be submitted.

Generally I would prefer it if more things were soft-deprecated by just being documented as “best use the other thing instead” rather than needing to be removed in a breaking change. Often the little breakages that I end up needing to adapt some code to come from things being removed but where I don’t think that the removal itself has any real benefit even if there is some alternative better thing that should/could be used.

3 Likes

Interesting. Other languages don’t do that. For example Java’s finalize method was deprecated since Java 9, but “deprecated, for removal” since Java 18.

Also, my question remains: if something is good enough not to be deprecated, why supply an alternative? Is it bad enough to replace, but not enough to complain when used?

1 Like