Пайланс утверждает, что код под if not dfs:
недоступен, и выделяет его серым цветом в VS Code.
import pandas as pd
def concat_dfs(dfs: tuple[pd.DataFrame | None], logger) -> pd.DataFrame | None:
# filter out dfs that are None, if any
dfs = [df for df in dfs if df is not None]
# concatinate dfs, if any are not None:
if not dfs:
logger.warning("All elements of dfs are None, so no inputs remain to be analyzed")
return None # greyed out as unreachable
else:
return pd.concat(dfs).sort_index()
Я пытался вернуть dfs
в одиночку, а не pd.concat(dfs).sort_index()
, так как в Pylance есть/были некоторые pd.concat
связанные ошибки.
Я также попробовал провести небольшой тест. Если Пайланс прав, я бы ожидал not dfs = False
, а вместо этого True
:
dfs = (None, None)
dfs = [df for df in dfs if df is not None] # dfs is an empty list
not dfs # returns True --> code should be reachable when every dataframe in dfs is None to begin with...
Проблема связана с подсказкой типа для dfs, которая не имеет смысла, когда вы пытаетесь использовать понимание списка. В VSCode понимание списка отмечено как ошибочное
tuple[X]
не является типом кортежа с нулевым или более X
значениями; tuple
и list
— это две совершенно разные вещи при типизации, гораздо менее похожие, чем типы tuple
и list
во время выполнения.
Чтобы добавить к существующему ответу @chepner: включите как можно больше правил и не перезаписывайте параметр.
Более надежная проверка кода может быть достигнута с помощью mypy. В этом случае mypy сообщит: Несовместимые типы в присваивании (выражение имеет тип «list[DataFrame]», переменная имеет тип «tuple[DataFrame | None]»)
Средство проверки достижимости не обращает внимания на ошибочную попытку присвоить список имени, статически введенному в виде кортежа, а также не пытается выяснить, может ли какое-либо конкретное значение dfs
создать пустой список. Заявленный статический тип dfs
— это tuple[pd.Dataframe | None]
, который состоит только из одноэлементных кортежей, и все такие значения являются истинными.
Причина, по которой код считается недостижимым, заключается в том, что подсказка типа для аргумента dfs
равна tuple[pd.DataFrame | None]
. Подсказки типов имеют приоритет над интерпретацией кода, и эта подсказка типа означает, что кортеж состоит из одного элемента, поэтому not dfs
никогда не может быть истинным.
Возможно, тип, который вы действительно хотите выразить, — это tuple[pd.DataFrame | None, ...]
(но вам следует избегать присвоения переменной типа, отличного от аннотации. Другими словами, вы не должны присваивать [df for df in dfs if df is not None]
, который является list
, dfs
.).
Вызов недоступен, если предположить, что статический тип
dfs
представляет собой непустой одноэлементный кортеж. Ваша попытка назначить список (пустой или нет) дляdfs
должна быть ошибкой типа.