6 ms·
The f-strings from 3.6 are a (relatively) recent feature that I have absolutely loved. I'd go so far as to say they are my favorite feature introduced by Pytho
by CivBase 7y ago
The f-strings from 3.6 are a (relatively) recent feature that I have absolutely loved. I'd go so far as to say they are my favorite feature introduced by Python 3.
I'm also looking forward to PEP-554 [0], which allows for "subinterpreters" for running concurrent code without removing the GIL or incurring the overhead of subprocesses.
[0] https://www.python.org/dev/peps/pep-0554/ https://www.python.org/dev/peps/pep-0554/
- enriquto 7y agof-strings are great. Much nicer than ".format". I hope in a next iteration of the language all strings will be f-strings by default, avoiding the need to prefix them by a silly "f".
- rolux 7y agoThat would of course be an absolute disaster, given that any user input could easily leak internal state and/or break your program.
- enriquto 7y agoI meant for inline strings (i.e., typed by the programmer). This is an inoffensive change. The only possible ``accident'' is when the programmer wants to write "{x}" instead of the value of x. This is such and exceptional case that it may be best treated by forcing to escape the curly brackets. If anything, user-input strings must be treated as tainted whatever the case.
- duckerude 7y agoThat would break any existing strings that use curly braces, including most legacy use of str.format and docstrings that include code examples with dictionaries. It would be a big backward compatibility issue.
- eesmith 7y agoA quick look at the Python stdlib gives shows some of the breakage that would occur: 1) existing uses of .format() would break: aifc.py: raise Error('marker {0!r} does not exist'.format(id)) 2) existing uses of "%" formatting would break: argparse.py: result = '{%s}' % ','.join(choice_strs) 3) many regular expressions would break: uuid.py: if re.fullmatch('(?:[0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value): 4) existing strings which contain uuids would break: uuid.py: >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}')
- ptx 7y agoThen you would run into the same problem Kotlin has with its raw strings – the brackets need to be escaped, but raw strings disable escaping, so you'd have to write r"{}" as r"{'\{\}'}" which is quite ugly and not very raw at all.
- Grue3 7y agoIt's not an exceptional use case at all. f-strings are pretty much useless for any non-trivial formatting: 1) customizable templates (can't allow the user to access arbitrary variables) 2) i18n (can't allow the translator to access arbitrary variables) 3) complex values being passed to .format() instead of some variable
- deleted 7y ago[deleted]
- BerislavLopac 7y agoExplicit is better than implicit.
- enriquto 7y agoSure, the curly brackets are explicit enough. What do you mean?
- hannibalhorn 7y agoSounds like PEP-544 is actually included in 3.8 on a "provisional" basis, which I guess just means they reserve the right to change the API. That's a killer feature for me, thanks for pointing it out!
- hannibalhorn 7y agoCorrection: So the PEP said it'll be in 3.8, but apparently it's been postponed to 3.9.
- dgrunwald 7y agoAs someone familiar with the Python C extension API, I somewhat doubt that it'll make 3.9 either. Disclaimer: I'm only familiar with CPython as a user of the extension API; I have no idea on how the Python team plans to address the challenges I'm mentioning here, and what their current progress is. The current extension module API encourages global state, e.g. types (and objects too) are allocated statically in a global C variable. For example, there is a global C variable `_Py_NoneStruct` that is the Python `None` value, and extension modules are accessing this variable directly. Every use of this object needs to adjust its reference count, and that reference count is directly stored within the C global variable. `_Py_NoneStruct` is currently even exposed in the PEP 384 stable ABI. Existing extension module binaries are commonly directly touching `_Py_NoneStruct.ob_refcnt` without any synchronization. Breaking the PEP 384 compatibility promise is fundamentally unavoidable here. One of two things must happen: Alternative one: All refcount operations must be made atomic for thread-safety. These are really really common in the Python interpreter, but atomic operations are expensive on modern CPUs (especially if there's contention). But multiple threads using the value `None` would be quite common in Python code, so I doubt you'd gain any speed even at today's core counts -- in fact I'd expect the constant inter-CPU-communication for the refcounts to make everything slower than just using a single core with today's Python! So alternative two, ensure no Python objects are shared between the subinterpreters. That's the plan. But that also means it's a breaking change for extension modules. And it's not just an ABI change (which would be handled by merely recompiling against the new headers). Any extension modules that do not yet support PEP 489 are already incompatible with subinterpreters, so that will take quite a bit of work until the ecosystem is upgraded. But there will probably also be some other breaking API changes. I think type objects are currently shared across subinterpreters, and those are frequently defined as a `Py_TypeObject` global variable in extension module code. Also, if every subinterpreter has its own GIL, extension modules calling `PyGILState_Ensure()` will have to specify which subinterpreter they will be using, so that the appropriate lock can be acquired. My prediction: 3.9 may have the basic functionality, but it still won't be able to run on multiple cores concurrently. That will take a bunch of more work and breaking changes, and will likely be released as Python 4.0. There will be another slow upgrade process ("my dependencies must upgrade before I can") until the Python ecosystem is multi-subinterpreter-compatible. But at least this one only affects extension modules.