Pylance сообщает: «Код недоступен», хотя мой тест показывает обратное

Пайланс утверждает, что код под 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 представляет собой непустой одноэлементный кортеж. Ваша попытка назначить список (пустой или нет) для dfs должна быть ошибкой типа.

chepner 23.07.2024 16:04

Проблема связана с подсказкой типа для dfs, которая не имеет смысла, когда вы пытаетесь использовать понимание списка. В VSCode понимание списка отмечено как ошибочное

SIGHUP 23.07.2024 16:04
tuple[X] не является типом кортежа с нулевым или более X значениями; tuple и list — это две совершенно разные вещи при типизации, гораздо менее похожие, чем типы tuple и list во время выполнения.
chepner 23.07.2024 16:05

Чтобы добавить к существующему ответу @chepner: включите как можно больше правил и не перезаписывайте параметр.

InSync 23.07.2024 16:11

Более надежная проверка кода может быть достигнута с помощью mypy. В этом случае mypy сообщит: Несовместимые типы в присваивании (выражение имеет тип «list[DataFrame]», переменная имеет тип «tuple[DataFrame | None]»)

SIGHUP 23.07.2024 16:28
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
5
83
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Средство проверки достижимости не обращает внимания на ошибочную попытку присвоить список имени, статически введенному в виде кортежа, а также не пытается выяснить, может ли какое-либо конкретное значение 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.).

Другие вопросы по теме