I have 2 pieces of code where default values could be None, but the None values are caught before the operation (>) or iteration of a list. Mypy is still producing an error message despite the fact that I can't see how None could get through in either case.
def plot_columns(df: pd.DataFrame, columns: list[str] | None = None):
if not columns:
columns = df.columns
for col in columns:
plt.plot(df[col])
def function_2(tup: tuple[float | int | None, float | int | None]) -> bool:
assert len(tup) == 2
if all(tup): # Also tried: if tup.count(None) == 0
return tup[0] > tup[1]
return False
In both cases mypy throws errors
first: Item "None" of "Optional[List[str]]" has no attribute "__iter__" (not iterable) [union-attr]
second (multiple similar errors): Unsupported operand types for > ("float" and "None") [operator]
Is there a better way to write these or a more pythonic way to do it? Or should I just ignore mypy on this one?
Edit: Appeased the first one by making it an empty list.
For the first one, pandas
itself doesn't seem to have typed df.columns
so that you can tell statically that the value is not None
. Try
def plot_columns(df: pd.DataFrame, columns: list[str] | None = None):
if not columns:
columns = cast(list[str], df.columns)
...
For the second one, all(tup)
doesn't seem to be on mypy
's list of recognized forms for type narrowing. (Or, type narrowing lets you narrow the type of tup
itself, not the elements of tup
.) Be more explicit:
def function_2(tup: tuple[float | int | None, float | int | None]) -> bool:
assert len(tup) == 2
a, b = tup
if a is None or b is None:
return False
returnn a > b