Make directories with parents and exist_ok. 🧵
Like this:
pathlib.Path("reports/2026").mkdir(parents=True, exist_ok=True)
#Python #DailyPythonTip
Make directories with parents and exist_ok. 🧵
Like this:
pathlib.Path("reports/2026").mkdir(parents=True, exist_ok=True)
#Python #DailyPythonTip
Use the "utf-8-sig" encoding for CSV files. 🧵
Many CSV files start with an invisible byte order mark (BOM).
When read as "utf-8", the first column name starts with a UTF-8 BOM character:
>>> rows[0]
{'\ufeffdate': '2026-10-01', 'kwh': '12.5'}
#Python #DailyPythonTip
Use the "utf-8-sig" encoding for CSV files. 🧵
Many CSV files start with an invisible byte order mark (BOM).
When read as "utf-8", the first column name starts with a UTF-8 BOM character:
>>> rows[0]
{'\ufeffdate': '2026-10-01', 'kwh': '12.5'}
#Python #DailyPythonTip
Match tuple-like data by shape with match-case. 🧵
>>> point = (3, 4)
>>> match point:
... case (x, y):
... print(f"2D point ({x}, {y})")
... case (x, y, z):
... print(f"3D point ({x}, {y}, {z})")
...
2D point (3, 4)
#Python #DailyPythonTip
Match tuple-like data by shape with match-case. 🧵
>>> point = (3, 4)
>>> match point:
... case (x, y):
... print(f"2D point ({x}, {y})")
... case (x, y, z):
... print(f"3D point ({x}, {y}, {z})")
...
2D point (3, 4)
#Python #DailyPythonTip
Match dictionaries by their keys with match-case. 🧵
It's handy for JSON from an API: does a response have an error key, or a type key with a specific value?
Without match, that's an if-elif chain of "in" checks, key lookups, and equality checks.
#Python #DailyPythonTip
Match dictionaries by their keys with match-case. 🧵
It's handy for JSON from an API: does a response have an error key, or a type key with a specific value?
Without match, that's an if-elif chain of "in" checks, key lookups, and equality checks.
#Python #DailyPythonTip
Make dataclasses instead of named tuples. 🧵
Do this:
@dataclass
class Room:
name: str
number: int
Not this:
class Room(NamedTuple):
name: str
number: int
#Python #DailyPythonTip
Make dataclasses instead of named tuples. 🧵
Do this:
@dataclass
class Room:
name: str
number: int
Not this:
class Room(NamedTuple):
name: str
number: int
#Python #DailyPythonTip
Match objects by their type and attributes with match-case. 🧵
A class pattern checks an object's type (like isinstance does) and the values of its attributes, capturing attributes into variables.
#Python #DailyPythonTip
Match objects by their type and attributes with match-case. 🧵
A class pattern checks an object's type (like isinstance does) and the values of its attributes, capturing attributes into variables.
#Python #DailyPythonTip
Don't use tuples for list-like data. 🧵
Do this:
colors = ["pink", "purple", "green", "blue"]
Not this:
colors = ("pink", "purple", "green", "blue")
#Python #DailyPythonTip
Don't use tuples for list-like data. 🧵
Do this:
colors = ["pink", "purple", "green", "blue"]
Not this:
colors = ("pink", "purple", "green", "blue")
#Python #DailyPythonTip
Split only as much as you need with maxsplit. 🧵
Do this:
key, value = line.split("=", maxsplit=1)
Not this:
key, *rest = line.split("=")
value = "=".join(rest)
#Python #DailyPythonTip
Split only as much as you need with maxsplit. 🧵
Do this:
key, value = line.split("=", maxsplit=1)
Not this:
key, *rest = line.split("=")
value = "=".join(rest)
#Python #DailyPythonTip
Remember that strings are iterables of strings. 🧵
Python doesn't have a character type, which usually makes things easier.
If name is a string, name[0] returns a string, and strings have a lower method:
>>> name = "Ada"
>>> name[0].lower()
'a'
#Python #DailyPythonTip
Remember that strings are iterables of strings. 🧵
Python doesn't have a character type, which usually makes things easier.
If name is a string, name[0] returns a string, and strings have a lower method:
>>> name = "Ada"
>>> name[0].lower()
'a'
#Python #DailyPythonTip
Use // instead of truncating with int. 🧵
Do this:
mid_point = len(sequence) // 2
Not this:
mid_point = int(len(sequence) / 2)
#Python #DailyPythonTip
Use // instead of truncating with int. 🧵
Do this:
mid_point = len(sequence) // 2
Not this:
mid_point = int(len(sequence) / 2)
#Python #DailyPythonTip
Import the whole module when a name isn't clear. 🧵
Do this:
import random
color = random.choice(colors)
Not this:
from random import choice
color = choice(colors)
#Python #DailyPythonTip
Import the whole module when a name isn't clear. 🧵
Do this:
import random
color = random.choice(colors)
Not this:
from random import choice
color = choice(colors)
#Python #DailyPythonTip
I only use whole-module imports for names that are unclear on their own. For datetime, I import the whole module but rename it to dt (see tip #257).
I only use whole-module imports for names that are unclear on their own. For datetime, I import the whole module but rename it to dt (see tip #257).
Don't delete "unnecessary" syntax that makes code more readable. 🧵
Some code is unnecessary but NOT unhelpful:
def earliest_date(date1, date2):
if parse(date1) < parse(date2):
return date1
else:
return date2
#Python #DailyPythonTip
Don't delete "unnecessary" syntax that makes code more readable. 🧵
Some code is unnecessary but NOT unhelpful:
def earliest_date(date1, date2):
if parse(date1) < parse(date2):
return date1
else:
return date2
#Python #DailyPythonTip
Separate the steps of a function with blank lines. 🧵
If you're using an auto-formatter like ruff or Black, you won't have control over most of your whitespace.
But how you use blank lines within functions is still up to you.
#Python #DailyPythonTip
Separate the steps of a function with blank lines. 🧵
If you're using an auto-formatter like ruff or Black, you won't have control over most of your whitespace.
But how you use blank lines within functions is still up to you.
#Python #DailyPythonTip
Return Boolean expressions directly. 🧵
Do this:
def is_even(n):
return n % 2 == 0
Not this:
def is_even(n):
if n % 2 == 0:
return True
else:
return False
#Python #DailyPythonTip
Return Boolean expressions directly. 🧵
Do this:
def is_even(n):
return n % 2 == 0
Not this:
def is_even(n):
if n % 2 == 0:
return True
else:
return False
#Python #DailyPythonTip
When creating lots of class instances, save memory with __slots__. 🧵
class Point:
__slots__ = ("x", "y", "z")
def __init__(self, x, y, z):
(self.x, self.y, self.z) = (x, y, z)
#Python #DailyPythonTip
When creating lots of class instances, save memory with __slots__. 🧵
class Point:
__slots__ = ("x", "y", "z")
def __init__(self, x, y, z):
(self.x, self.y, self.z) = (x, y, z)
#Python #DailyPythonTip
Avoid making metaclasses if you can. 🧵
There's usually an easier tool for the job.
Metaclasses customize the behavior of CLASSES the same way classes customize the behavior of their instances.
#Python #DailyPythonTip
Avoid making metaclasses if you can. 🧵
There's usually an easier tool for the job.
Metaclasses customize the behavior of CLASSES the same way classes customize the behavior of their instances.
#Python #DailyPythonTip
Always use functools.wraps when making a decorator. 🧵
A decorator REPLACES a decorated function with the function that was returned from calling the decorator.
#Python #DailyPythonTip
Always use functools.wraps when making a decorator. 🧵
A decorator REPLACES a decorated function with the function that was returned from calling the decorator.
#Python #DailyPythonTip
Avoid needless deep copying. 🧵
Often a deepcopy call can be replaced by a comprehension, a slice, or some other operation that makes new objects.
When you copy a list of dictionaries, you get a NEW list pointing to the SAME dictionaries.
#Python #DailyPythonTip
Avoid needless deep copying. 🧵
Often a deepcopy call can be replaced by a comprehension, a slice, or some other operation that makes new objects.
When you copy a list of dictionaries, you get a NEW list pointing to the SAME dictionaries.
#Python #DailyPythonTip
Use exceptions to pass error messages to users. 🧵
Catch exceptions with messages users shouldn't see, and raise your own with a message they SHOULD see:
class WeatherError(Exception):
"""Raised when we can't show the user a forecast."""
#Python #DailyPythonTip
Use exceptions to pass error messages to users. 🧵
Catch exceptions with messages users shouldn't see, and raise your own with a message they SHOULD see:
class WeatherError(Exception):
"""Raised when we can't show the user a forecast."""
#Python #DailyPythonTip
Write context managers with contextlib.contextmanager. 🧵
Instead of making a class with __enter__ and __exit__ methods, we can make a context manager out of a function:
#Python #DailyPythonTip
Write context managers with contextlib.contextmanager. 🧵
Instead of making a class with __enter__ and __exit__ methods, we can make a context manager out of a function:
#Python #DailyPythonTip
Keep "try" blocks small with an "else" clause. 🧵
try:
count = int(text)
except ValueError:
print("That's not a number")
else:
print(f"Counting to {count}")
#Python #DailyPythonTip
Keep "try" blocks small with an "else" clause. 🧵
try:
count = int(text)
except ValueError:
print("That's not a number")
else:
print(f"Counting to {count}")
#Python #DailyPythonTip
Check regex matches with the walrus operator. 🧵
Do this:
if match := UNITS_RE.search(string):
return match.groups()
Not this:
match = UNITS_RE.search(string)
if match:
return match.groups()
#Python #DailyPythonTip
Check regex matches with the walrus operator. 🧵
Do this:
if match := UNITS_RE.search(string):
return match.groups()
Not this:
match = UNITS_RE.search(string)
if match:
return match.groups()
#Python #DailyPythonTip
Pretty-print data structures with pp. 🧵
>>> from pprint import pp
>>> pp(user)
{'name': 'Trey',
'languages': ['Python', 'JavaScript'],
'address': {'city': 'San Diego', 'state': 'CA'}}
#Python #DailyPythonTip
Pretty-print data structures with pp. 🧵
>>> from pprint import pp
>>> pp(user)
{'name': 'Trey',
'languages': ['Python', 'JavaScript'],
'address': {'city': 'San Diego', 'state': 'CA'}}
#Python #DailyPythonTip