Remix.run Logo
Python string literals are kinda funny(sebsite.pw)
56 points by jandeboevrie 3 days ago | 42 comments
PyWoody 2 hours ago | parent | next [-]

Whenever I read people's takes about Python on HN, I always feel like I'm using an entirely different language.

kstrauser 34 minutes ago | parent [-]

I feel ya. I don’t write a lot of it anymore, but have written probably hundreds of thousands of lines over the years. It has a few rough edges, but over all it’s solid and I’ve used it to make lots things I’m proud of.

dwdz 3 hours ago | parent | prev | next [-]

I'm not a fan of f-strings.

I feel like 90% of new Python features in the last 10 years just increased language complexity without any benefit.

ForceBru 2 hours ago | parent | next [-]

I'm a HUGE fan of f-strings and I think they should be added to more or less every language in existence. (This is just to show how much I like f-strings, not to be taken literally) `printf`-style format strings seem outdated: why use format strings when I can put my variables IN THE STRING? I want the result of `x+y` to be put {HERE} in this string. Well, just write `"This is here: {x+y} blah"` — it makes perfect sense and immediately lets me see what the resulting strings generally look like.

Basic usage is a no-brainer: write your string, put variables or short expressions in curly braces, add `printf`-style format specifiers after the colon. This is also great because it's a natural extension of `printf`-style format strings.

Of course you can write complicated and confusing f-strings. But then you can write complicated and confusing... anything, really. Many programming languages have extremely weird quirks and cases where basic syntax can be transformed into an unreadable monstrosity, like C syntax for pointers to functions and arrays.

Sure, this increases the language's complexity, but you don't have to use all of it to reap the benefits.

Izkata an hour ago | parent | next [-]

Those aren't the only two options. Like GP I don't like f-strings, but there was something introduced before that: the format function.

  "The thing is {foo}, and also {foo} again".format(foo=x+y)
It also supports positional with empty {}. And like f-strings, you can put formatting information after a colon.

%-based printf-style did also have named variables like this but it seemed less known.

layer8 an hour ago | parent | prev [-]

> why use format strings

Because these are used for locale-specific configuration data. `"This is here: {x+y} blah"` on the other hand isn’t a string (mere data), it’s a program, because you can have arbitrary expressions inside the braces. You don’t want to repeat the `x+y` in each localization file.

I have nothing against ergonomic program constructs for composing strings, but please let’s not confuse such program constructs with mere string literals.

zdragnar 32 minutes ago | parent [-]

If your string needs to be presented in multiple locales, you probably want to go a step further and use something like the ICU syntax and a proper parser and formatter rather than rely on manually formatting things yourself. Otherwise, that dynamic data is going to give you headaches when you have to deal with plurals and genders and such.

layer8 27 minutes ago | parent [-]

I’m not sure what you mean by manual formatting. You do need a place in your program where you fill in the parameters into the respective localized string template. I agree that the printf format syntax is somewhat limited for localization [0]. But whatever localization string format you use, you don’t want arbitrary expressions embeddable within it.

[0] though GNU libc does let you extend it: https://sourceware.org/glibc/manual/latest/html_mono/libc.ht...

vova_hn2 an hour ago | parent | prev | next [-]

I like f-strings but I don't like that there are at least five ways to format stings.

1. %-formatting [1]

2. str.format [2]

3. string.Template [3]

4. f-string [4]

5. t-string [5]

What happened to "one-- and preferably only one --obvious way to do it"? [6]

Also, the way string formatting interacts with logging is a total mess. People just pass f-strings to logging, which seems to be an intuitive way to do it. Except it limits your options if you want to collect structured logs and it doesn't allow you to use late evaluation based on log level.

[1] https://docs.python.org/3/library/string.html#format-example...

[2] https://docs.python.org/3/library/stdtypes.html#str.format

[3] https://docs.python.org/3/library/string.html#string.Templat...

[4] https://docs.python.org/3/reference/lexical_analysis.html#f-...

[5] https://docs.python.org/3/reference/lexical_analysis.html#t-...

[6] https://peps.python.org/pep-0020/

gucci-on-fleek an hour ago | parent [-]

> What happened to "one-- and preferably only one --obvious way to do it"?

There arguably still is—just use f-strings for everything, unless you need to support ancient Python, in which case use %-formatting.

t-strings are a special case, but in theory most functions should only accept regular strings or templates, so there should only be one choice there too.

> Also, the way string formatting interacts with logging is a total mess [...] it doesn't allow you to use late evaluation based on log level.

This all seems to be a side-effect of the fact that string formatting produces static strings, so I don't think that there's much that can be done here (but maybe t-strings can be creatively used here somehow).

vova_hn2 2 minutes ago | parent [-]

> maybe t-strings can be creatively used here somehow

Maybe they could, but I would be the first to oppose introducing creative ways to do logging or string formatting.

Such basic things should be done in the most standard way possible to reduce cognitive effort required to read and understand the code.

But the standard way is kinda ugly. Most people would expect f-strings to be used for "normal" string formatting and %-style to be used for logging, because it is the default and most codebases do it this way. Therefore, you basically forced to have (at least) two different formatting syntaxes in your codebase.

I say "at least", because if the program serves html pages, you most likely also have some other template engine like jinja...

ajrouvoet 2 hours ago | parent | prev | next [-]

It is baffling to me that Python seems to insist on reinventing language features and coming up with the most incomprehensible of designs. The whole dataclass and serialisation ecosystem comes to mind, as well as the evolution of typing.

The language exposes so much of its internals that even if the design were consistent, the ecosystem of (buggy) libs and tools makes it inconsistent.

LPisGood 2 hours ago | parent [-]

PKL files and the entire multiprocessing paradigm is one of the worst experiences I’ve ever had with a programming language feature. Surely there has to be a better way.

odyssey7 14 minutes ago | parent | prev | next [-]

It doesn’t have to be beneficial, it just has to be “pythonic.”

analog31 3 hours ago | parent | prev [-]

Indeed, and I get that one can ignore those features (I do), but finding them in existing code or having the AI coding agent use them diminishes the "easy for beginners" aspect.

ForceBru an hour ago | parent | next [-]

How is, say, `age = 5; print(f"Age: {age} years old")` not easy for beginners? IMO it's as easy as it gets: you want the value of `age` printed {HERE}, so you just put it where you want it, surrounded by curly brackets.

orf 2 hours ago | parent | prev [-]

Are f-strings not easy for beginners? What would you prefer instead?

analog31 9 minutes ago | parent [-]

I'd prefer one way of doing things. I do understand that the improvements to string literals are improvements, but it means there are multiple things to learn.

phyzome 2 hours ago | parent | prev | next [-]

Goofy edge cases aside, I think f-strings are great.

vova_hn2 an hour ago | parent | prev | next [-]

I think this is pretty intuitive (I was able to answer the question correctly before opening the spoiler), but I really like raw string designs in Rust and C++11 that allow you to stop worrying about escaping completely.

ethin an hour ago | parent | prev | next [-]

Not really about the content of the blog post but am I the only one bothered by the complete lack of capitalization? Granted it may be because of my screen reader but my TTS engine of choice doesn't pause on un-capitalized words/sentences/phrases/etc. which follow a full stop, so this post unless I read it line by line (minus the code) just blends into complete noise.

cocodill 2 hours ago | parent | prev | next [-]

do not get the funny part of the pythons string.

xg15 3 days ago | parent | prev | next [-]

here's a valid f-string:

>>> f'{'}'}' '}'

Huh? I remember learning the rule that you can't nest quotes inside fstrings if they are the same kind (unlike in bash) - e.g

  f"{mydict["foo"]}"
would be a syntax error, but

  f"{mydict['foo']}"
or

  f'{mydict["foo"]}'
would be valid.

The reason being the same like for the rstring weirdness: The lexer comes first and identifies the string literal, then for fstrings, the python parser is invoked again for each {...} expression to parse it.

This is unlike other nested expressions, which are already split up by the lexer and then parsed in one go.

Did that change at some point?

xg15 2 days ago | parent [-]

Update: They really changed it! (in python 3.12)

There was a PEP about it:

https://stackoverflow.com/questions/78388333/nested-quotes-i...

https://docs.python.org/3.12/whatsnew/3.12.html#pep-701-synt...

globular-toast an hour ago | parent [-]

Wow, I didn't know this either. I find it a bit crazy. It must make no sense without syntax highlighting. But I suppose who writes code without highlighting any more?

dotancohen an hour ago | parent [-]

It's been a long time since I've had to SSH into a box to fix an issue in production. But it is comforting to know that I _could_.

VI (not even VIM) on minimal Debian installs does not have syntax highlighting.

vova_hn2 9 minutes ago | parent [-]

How often do you have SSH access to a box but don't have SFTP access?

Most IDEs support editing files on a remote machine through SFTP.

madprops 2 hours ago | parent | prev | next [-]

Great new way to write blog posts!

smitty1e 3 hours ago | parent | prev | next [-]

Whenever I'm building a JSON document, I revert to the old %s syntax just because it's more tidy than an f-string.

folkrav 3 hours ago | parent [-]

Am I understanding that you’re building JSON with string interpolation? If so any special reason you wouldn’t build a dict and json.dumps() it?

TZubiri 2 hours ago | parent | prev [-]

Been using python for almost 10 years. I never use any of the funky strings.

Instead of reading like 10 PEPs for f strings, I just use the + operator on strings and backslash escaping, big whoop.

PyWoody 2 hours ago | parent | next [-]

Instead of 10 PEPs, you could read one helpful cheatsheet: https://www.pythonmorsels.com/string-formatting/#cheat-sheet....

andai 2 hours ago | parent | prev | next [-]

age = 32

print(f"Age: {age}")

Thus concludes the lecture on f-strings.

kzrdude an hour ago | parent | next [-]

I find it funny and satisfying that Python has converged to it's own "printf", by which I mean print(f"").

layer8 35 minutes ago | parent | prev [-]

It’s unclear what the big advantage is over `print("Age: "+age)`. It’s even more characters, in that specific example.

kzrdude a minute ago | parent | next [-]

The + solution doesn't scale up to format specifiers like the f-string does. Precision, padding, other modifiers.

mixmastamyk 2 minutes ago | parent | prev | next [-]

Toy examples aren’t the use case, rather multiple variables or expressions, perhaps with formatting (padding) as well.

f-string is shorter, less err prone, and faster for medium complexity or above.

kstrauser 29 minutes ago | parent | prev [-]

If age is a number, that won’t work.

layer8 24 minutes ago | parent [-]

Admittedly I’m not so familiar with Python; it does work in Java. In that case, introducing a less hazardous string concatenation operator would seem more universally useful.

kstrauser 5 minutes ago | parent [-]

In Python, that less hazardous string concatenation operator is an f-string.

smohare 2 hours ago | parent | prev [-]

Right, because x + " " + y is more clear than of simply f"{x} {y}".

Been using python for longer than 10 years and immediately started using f-strings when I could. It takes almost no time to understand the basics.

layer8 33 minutes ago | parent [-]

Personally I do find the first version clearer, because it is based on general language rules.