#29988 closed Cleanup/optimization (fixed)
Use f-strings for string formatting once support for Python 3.5 is dropped
Reported by: | Jaap Roes | Owned by: | Carlton Gibson |
---|---|---|---|
Component: | Core (Other) | Version: | |
Severity: | Normal | Keywords: | fstrings python3.6 |
Cc: | Tom Forbes | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
The end of life date for Python 3.5 is 2020-09-13. This means that the next version of Django after this date (earliest 3.1?) can start using Literal String Interpolation (f-strings) for string formatting.
Not only are f-strings very programmer friendly, they are also very fast (source: A Closer Look At How Python f-strings Work).
Change History (11)
follow-up: 3 comment:2 by , 6 years ago
Component: | Uncategorized → Core (Other) |
---|---|
Triage Stage: | Unreviewed → Someday/Maybe |
See the django-developers discussion for some concerns (e.g. no i18n support and Florian's comment, "Knowing what certain members of the core team think about those f-strings, I think there will be first a big discussion if we will allow them at all in Django's codebase.").
comment:3 by , 6 years ago
That discussion (and the one linked to) seem to be more about (or digress into) using .format
instead of %
formatting. I'm not in favor of going through and replacing all %
formatting with .format
calls. Instead Django should just start using a f-strings feature ("Literal String Interpolation") introduced in Python 3.6 when/where possible.
I'm aware of the concern about i18n, but a lot of the string formatting/concatenation in Django isn't translatable text and therefore isn't affected by that issue at all.
This is really more about replacing code like this:
path=handler.__module__ + '.' + handler.__qualname__,
with path=f'{handler.__module__}.{handler.__qualname__}'
return "{}({}, {})".format(self.__class__.__name__, self.sql, self.params)
with return f'{self.__class__.__name__}({self.sql}, {self.params})'
and sql = '%s %s%s ON (%s)' % (self.join_type, qn(self.table_name), alias_str, on_clause_sql)
with sql = f'{self.join_type} {qn(self.table_name)}{alias_str} ON ({on_clause_sql})'
Which (arguably) benefits the readability and can have a positive performance impact on the Django code base.
comment:4 by , 6 years ago
Cc: | added |
---|
comment:5 by , 5 years ago
Has patch: | set |
---|
A first pass that only modifies simple uses of .format()
such that the string expressions are shorter, are not translated strings, and do not nest quotes.
comment:6 by , 5 years ago
I'm in favor of this change. However, I'm a bit hesitant for error messages. They are not translatable now, but they could in the future (and most should IMHO, but this is another story).
comment:7 by , 5 years ago
Django 2.2 is the last to support Python 3.5 so I'm in favor of using f-strings in Django 3.1 for the readability improvement.
comment:8 by , 5 years ago
I am in favor well where it makes sense and has clear readability benefits. I don't have strong rules to provide but I've already seen this feature abused in the wild to compose complex formatting string which makes hard to differentiate placeholders from their delimiters when function calls are involved.
I also share you Claude's concerns about error messages and logging message templates.
comment:9 by , 4 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
Triage Stage: | Someday/Maybe → Ready for checkin |
We pushed this forwards after discussion on the mailing list. PR
Current master has 193 matches for
find . -type f -name "*.py" -exec grep -n "['\"]\.format(" {} + | wc -l
. (All direct invocations of theformat
method on a string literal).There are 3435 matches for
find . -type f -name "*.py" -exec grep -n "['\"] %" {} + | wc -l
(All uses of the%
operator on a string literal).There's probably many more places where
.format
or%
formatting is used on a variable string.EDIT: There's also 435 matches for string concatenation (
find . -type f -name "*.py" -exec grep -En "(['\"] \+)|(\+ ['\"])" {} + | wc -l
)