9 ms·
Python string literals are kinda funny
- DonHopkins 1mo agoIn his 2017 PyCon Israel keynote, "The Fun of Reinvention", Dave Beazley made a wonderfully mischievous case for taking advantage of new Python features instead of making every new project carry the accumulated baggage of old Python versions. Talking about Python 3.6, he said it was "probably one of the most major Python releases that has ever been made." His demonstration intentionally used new features that made the code incompatible with older interpreters. This was a prototype, so why not use the interesting new tools? He was especially enthusiastic about f-strings: "F-strings are just awesome." I was originally skeptical about them, but he convinced me to reconsider. One implementation detail that later helped win me over was that CPython 3.6 added dedicated FORMAT_VALUE and BUILD_STRING opcodes for f-strings. That does not mean an f-string is faster than simply doing a + b when both values are already strings -- simple concatenation usually wins that particular race -- but f-strings are generally cleaner, and often faster than older formatting machinery such as str.format(). I agree with his argument. There are vanishingly few situations in which a new project genuinely must support ancient Python releases. If your employer refuses to let you use a reasonably current version without a concrete technical reason, that is a warning sign. Life is too short to program indefinitely for obsolete interpreters. The keynote: https://www.youtube.com/watch?v=js_0wjzuMfc https://www.youtube.com/watch?v=js_0wjzuMfc Beazley's other talks: https://www.dabeaz.com/talks.html https://www.dabeaz.com/talks.html
- xg15 1mo agohere'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 1mo agoUpdate: They really changed it! (in python 3.12) There was a PEP about it: https://stackoverflow.com/questions/78388333/nested-quotes-in-f-string-with-python-3-12-vs-older-versions https://stackoverflow.com/questions/78388333/nested-quotes-i... https://docs.python.org/3.12/whatsnew/3.12.html#pep-701-syntactic-formalization-of-f-strings https://docs.python.org/3.12/whatsnew/3.12.html#pep-701-synt...
- globular-toast 1mo agoWow, 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 1mo agoIt'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 1mo agoHow 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.
- dotancohen 1mo agoIt would be scp, not sftp, but I often don't know what I'm about to edit until I get in there and dig around.
- vova_hn2 1mo agoNo, I was talking about SFTP, not scp. OpenSSH server has SFTP enabled by default. You can mount it using sshfs or browse it using any SFTP client (or any program with embedded SFTP client, which is most IDEs). So, if "digging around" means looking at folders' structure, you can do it through SFTP without copying everything (unlike scp or rsync). And if digging around means running commands, nothing prevents you from having a session for running commands open in parallel.
- smitty1e 1mo agoWhenever I'm building a JSON document, I revert to the old %s syntax just because it's more tidy than an f-string.
- folkrav 1mo agoAm 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?
- smitty1e 1mo agoWhen there is a multiline template, you can make it look natural within json_doc = '''{}''' % some_dictionary and then populate json_doc via %(some_dictionary_key)s values inside of the brackets. I find it more readable. Furthermore, json_doc can now live elsewhere, if sizeable, and get imported. I guess that template strings may be the newer way to do this, but this is very backward compatible.
- dwdz 1mo agoI'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.
- analog31 1mo agoIndeed, 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.
- orf 1mo agoAre f-strings not easy for beginners? What would you prefer instead?
- analog31 1mo agoI'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.
- ForceBru 1mo agoHow 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.
- TZubiri 1mo agoBeen 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.
- smohare 1mo agoRight, 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 1mo agoPersonally I do find the first version clearer, because it is based on general language rules.
- TZubiri 1mo agoEspecially if you come from other languages. a + " " + b will be clearer to devs that aren't senior python developers. the f string thing is just a marginal improvement at the cost of alienating other devs. But it's great for gatekeeping and job security.
- shooly 1mo ago> come from other languages According to Wikipedia[1] the history of string formatting goes back to 1950s. Also, basically every major programming language these days implements it in some form. [1] https://en.wikipedia.org/wiki/Printf https://en.wikipedia.org/wiki/Printf > senior python developers > great for gatekeeping and job security Ah, okay, it's just a troll.
- TZubiri 1mo agoBut the link you shared describes a syntax that is very different. "%T", T t not "{ (expr).__str__()} " > Ah, okay, it's just a troll. If that helps you sleep at night
- phyzome 1mo agoGoofy edge cases aside, I think f-strings are great.
- cocodill 1mo agodo not get the funny part of the pythons string.
- PyWoody 1mo agoWhenever I read people's takes about Python on HN, I always feel like I'm using an entirely different language.
- kstrauser 1mo agoI 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.
- Walf 1mo agoThat you know how to use the language without such oddities presenting any difficulty does not make them less strange. That r-string parsing solution is fine for the interpreter, but we are not interpreters, so it's not a logical outcome for Python authors, The most puzzling thing is few languages use the absolute simplest solution to escaping quotes, which happens to be especially useful for non-expanded literals, and that's good ol' quote-doubling. Difficult for Python to introduce now since it'd be a bc-break for implied concatenation, but if space were required between them, we could have had x = r'ex\x20cape!\' y = 'diff''rent' z = 'diff' 'erent' respectively containing ex\x20cape!\ diff'rent different TOML has a similar issue: it is impossible to store its delimiter for non-expanded multi-line strings inside a multi-line non-expanded string. There's no method to escape it. Whilst this is rarely an issue in practice, it's odd that there's unnecessary difficulty in writing about TOML inside a TOML document. Again, it could have used the simpler quote-doubling method for all strings (even easier because no concatenation), with similar rules for non-expanded and multi-line variants. Then there would be no limitation on what can be stored in any literal type. Instead it has a peculiarity that's illogical and offers no benefit to us authors.
- madprops 1mo agoGreat new way to write blog posts!
- ethin 1mo agoNot 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.
- vova_hn2 1mo agoI 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.