This ship has sailed. Give it up and redesign your API not to rely on string literals or to use them another way, instead of proposing breaking changes for tens, even hundreds of thousands of other users.
You can do this:
def sprintf(fmt, *args):
return fmt % args
and then have your own code style guide that requires the use of this function rather than directly doing percent formatting. This has the same effect as the deprecation.
But he still won’t be able to overwrite %
for strings to work the way he wants.
Practically speaking, even if there was support for that idea[1], it would take several years before it actually happened. So unless @cjdrake wants to pause development that long, he needs to come up with a workaround anyway.
and to be clear, I don’t think there is any ↩︎
I opened the first link of OP, it shows a problem where a library cannot override __rmod__
from str
if I get it right.
→ Actually deprecating %
will not solve anything.
→ Probably allowing to override __rmod__
in subclasses of str
is actually not so difficult and solves the problem… idk.
Currently:
>>> "abc" % 12
...
TypeError: not all arguments converted during string formatting
Would it break much code or cause much weird behaviour or confusion, if instead of a TypeError when evaluating s % y
, str.__mod__
first checks if the string s
actually contains any %s
or %d
fields to interpolate with y
? If there are no %s
fields etc., it could raise NotImplemented, or call __rmod__(y, s)
if there is such a method on the right hand argument?
String literals aren’t instances of subclasses of str
though, they are instances of str
(literally, bubumtish), so that won’t meet OP’s feature request. He can already require his users to create a wrapper class and make his users wrap their string literals in it.
This is a great idea: only %
-format strings implement the %
operator.
Replacing the TypeError
with more subtle behavior follows John Ousterhout’s principle of “defining errors out of existence”.
I haven’t been using it for long, but I think these old format-specifiers do not have a fully viable replacement option, especially regarding the (old way of) interactive prompting through the terminal.
this is a cute idea, but the following does currently work:
"hi" % ()
and I imagine this is being used a lot. In functions that do (s, *args) => s % args
.
Regardless, it does seem fair that it would be better for the string to look for .__rmod__
on the right-hand object when the string.__mod__
operator fails. Instead of immediately raising TypeError: not all arguments converted during string formatting
.
I don’t know how hard that is to implement though.
How does that align to the “Zen of Python” ?
I speak more computer languages than human ones, but ive never liked the fprintf formatting. In my view It is a write-only notation whereas good syntax must be simple to read and review.
No need to remove it, but to me its already deprecated. Ill sacrifice computer speed to avoid human errors even on constrained systems.
You could say the exact same thing about arithmetic notation or regular expressions though. One person’s “write-only notation” is another’s “compact representation”. Percent formatting is consistent and readable, but like any other minilanguage, requires comprehension.
The beauty of percent formatting above many others is that this comprehension could have come from any of a number of other programming languages, and conversely, learning it in Python will benefit you in any of those languages too.
No need to learn, just need to unforget what I learned 30+ years ago. Nothing against terse oneliners either.
But I think the point and preferences either way are moot, as the proposed is not about % in formatting, but for the % operator.
I can see an argument for introducing such a function. It would be structurally equivalent to .format()
i.e. easier to learn and remember. By using args and kwargs, it replaces the str % dict
, str % tuple
and str % val
patterns. In particular it also circumvents the issue that str % val
for a single val does not work if that val is a tuple.
As others have said the %-placeholder pattern is still helpful when the string you want to format has curly braces itself (regexps, jinja templates, latex code …). Giving it a respective formatting function would strengthen it’s usability.
This is independent on whether the % operator should be depreciated or its behavior can be changed for specific cases, but such a formatting function would likely make arguments for these changes easier because the valid %-placeholder use cases would have a better API and wouldn’t be tied to the % operator.
I don’t see why str
should work with your custom type—it’s a distinct type, specifically designed to treat %
as formatting, not as a mathematical operation.
I imagine it’s because the class of x
implements __rmod__
, but that’s not being called because str.__mod__
is being checked first[1].
IMO, this is a design issue with the library, and while removing the str.__mod__
operator would “fix” it, no-one is going to accept that much breakage just to allow one library to continue with a questionable design. Far better would be for the library to work with a string subclass, or some other custom type, so the usage would be x % s("lit")
or s("lit") % x
.
The s
class could be as simple as:
class s(str):
def __mod__(self, other):
# Your implementation here
Technically, str is implemented in C, but the point’s the same ↩︎
I’m already doing something like that:
>>> from bvwx import *
>>> bits("4b1000") % "4b0101" # 8 % 5 = 3
bits("4b0011")
>>> bits("4b1000") % bits("4b0101") # 8 % 5 = 3
bits("4b0011")
>>> mod("4b1000", "4b0101") # 8 % 5 = 3
bits("4b0011")
>>> "4b1000" % bits("4b0101") # this one doesn't work
"4b1000"
I’m not blocked. I would describe this as an inconvenience.
Regardless, I still think the str %
operator is antiquated and inconsistent. This is my first ever post on discuss.python.org. I thought “Ideas” was a safe place to suggest crazy things. We’ve already brainstormed a few ideas to restrict the scope of the proposal .
If by “safe” you mean “you won’t get banned”, then yes, this is. But if you mean “the idea won’t get critiqued”, then no, no place is safe from that
In that case, I’ll be sure to make my second post much more controversial .
I look forward to it. The answer will probably be a “No” again. But I wouldn’t have thought about the tweak to raise NotImplemented and looked at the C code, if you hadn’t have proposed this one.
One option (not mentioned yet, I think) might be a soft deprecation.
From PEP 3101 we read: “This PEP proposes a new system for built-in string formatting operations, intended as a replacement for the existing ‘%’ string formatting operator.” So, PEP intention was clear.
Yet, we have section in the Tutorial, which suggests using “old” string formatting. Why not remove this for beginning?
@ngoldbaum, can you elaborate more?
So far, @bwoodsend example — one real case of shortcomings of the “new-style” string formatting in the whole thread. (E.g. writing LaTeX.) It would be nice to make workaround for this, yet I can live with this issue.