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.
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.
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.
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.
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.
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.
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.
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!
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.
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:
We cannot deprecate %-operator for the forseeable future, because it is too much in use.
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.
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.
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.
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.
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?