9.13 Best Practices
Reaching for join() instead of += in loops, f-strings as the default formatting choice, comparing strings with == rather than is, and parsing untrusted text with the standard library instead of eval().
Build Large Strings with join(), Not +=
Accumulating a string with += inside a loop is O(n²); collecting pieces in a list and calling "".join(...) once is O(n). See 9.11 Memory and Performance for the full explanation.
result = " ".join(word_list) # preferred over looped +=
Default to f-Strings, but Know the Exceptions
f-strings are the fastest and most readable choice for new code — but only when the template itself is a literal in the source. If the template is loaded from a config file or comes from an untrusted source, use .format() or string.Template instead (see 9.6 String Formatting).
Compare Content with ==, Never Identity with is
String interning is a CPython implementation detail, not a language guarantee — two equal strings built at runtime are not guaranteed to be the same object. Always compare string content with ==.
>>> a = "hello"; b = "".join(["h", "e", "l", "l", "o"])
>>> a == b, a is b
(True, False) # equal content, but NOT the same object
Parse Structured Data with the Standard Library, Not eval()
Use json.loads(), ast.literal_eval(), or yaml.safe_load() to parse data — never eval(), which executes arbitrary code and is a serious security risk on any input that isn’t fully trusted.
Specify Encoding Explicitly
Always pass an explicit encoding="utf-8" (or whatever is correct) when reading or writing files, rather than relying on the platform default — the default varies by OS and can silently corrupt non-ASCII text.
Quick Interview Answer
“Five habits cover most of what matters day to day: build large strings with
''.join(...)instead of+=in a loop; default to f-strings for new code, but fall back to.format()/string.Templatewhen the template itself is data or untrusted; always compare strings with==, neveris, since interning isn’t a language guarantee; parse structured text withjson.loads()/ast.literal_eval()rather thaneval(), which is a security risk on untrusted input; and specify file encoding explicitly instead of relying on a platform default that can silently corrupt non-ASCII text.”
Common Mistakes
- Reaching for
eval()to parse a dict-like or list-like string instead ofast.literal_eval()orjson.loads()—eval()executes arbitrary code, which is unsafe on anything not fully trusted. - Opening a file with
open(path)and no explicitencoding=, then hitting aUnicodeDecodeErroror silent mojibake on a different OS or locale. - Relying on
isfor string comparison because it happened to work in a quick REPL test — interning behavior differs between short literals and runtime-built strings.
Add More Questions to This Guide
Know a question that should be here? Share it and help the community!
Open Google Form