Mypy выдает ошибку «Значение типа «Строка | Нет» не индексируется» для строки, начинающейся с «x=":
from pyspark.sql import DataFrame
from pyspark.sql import functions as f
def somefunction(df: DataFrame, column_name: str) -> DataFrame:
x = df.select(f.min(f.col(column_name))).first()[0]
return df.withColumn('newcolumn', f.col(column_name) + x)
Как я могу добавить проверку типа, которая проходит через mypy?






df.select(...) возвращает значение типа Row | None, что означает, что фактическое возвращаемое значение может быть Row или None. Вы не можете индексировать None, поэтому вы не можете индексировать значение типа Row | None, пока не убедитесь, что это определенно не так None. (По сути, интерфейс типа объединения — это пересечение отдельных типов: с A | B можно делать только то, что можно делать с A и B.)
Один из способов сделать это — использовать сужение типа: проверив, равно ли возвращаемое значение None, вы можете перейти к коду со статическим типом NoneType или к коду со статическим типом Row.
# reveal_type(result) == Row | None
result = df.select(f.min(f.col(column_name))).first()
if result is None:
# reveal_type(result) == None
do what needs to be done if no row is returned
else:
# reveal_type(result) == Row
x = result[0]
return df.withColumn('new column', f.col(column_name) + x)
Возможно, вы знаете, что конкретный аргумент df.select не может потерпеть неудачу, но mypy — нет.
Другой вариант, если вы абсолютно уверены, что получите ответный знак Row, — использовать cast, чтобы раскрыть mypy секрет.
x = typing.cast(Row, df.select(...))[0]
return df.withColumn(...)
Однако это рискованно. mypy поверит cast, и если df.select(...) вернет None, вы получите ошибку времени выполнения, хотя mypy говорит, что все в порядке.