
在 Polars 中,列的数据类型是全局一致的,无法通过行级表达式(如 pl.col().shrink_dtype())动态判断每行类型;应使用 df.collect_schema() 或 df.schema 获取列级 Schema,并结合 dtype 选择器进行类型感知的批处理。
在 polars 中,列的数据类型是全局一致的,无法通过行级表达式(如 `pl.col().shrink_dtype()`)动态判断每行类型;应使用 `df.collect_schema()` 或 `df.schema` 获取列级 schema,并结合 dtype 选择器进行类型感知的批处理。
Polars 的核心设计原则之一是列式强类型一致性:同一列中所有值共享完全相同的物理数据类型(如 list[i64]),该类型在 DataFrame 构建时即确定,且对整列统一有效。因此,试图在 .select() 中用表达式(如 pl.col("list_column").shrink_dtype() == pl.List)逐行检查类型,不仅语义错误,而且技术上不可行——shrink_dtype() 是一个 eager 操作,仅适用于 Series 或 DataFrame 的 eager 模式,不能在 lazy 表达式上下文中调用,更不支持返回类型对象用于逻辑比较。
正确的做法是直接访问 Schema 层信息:
import polars as pl
df = pl.DataFrame({"list_column": [[1, 2], [3, 4], [5, 6]]})
# ✅ 推荐:获取列类型(lazy 或 eager 均适用)
schema = df.collect_schema() # 返回 Schema 对象(Polars ≥ 0.20.0)
print(schema["list_column"]) # → List(Int64)
# 或兼容旧版本
print(df.schema["list_column"]) # 同样输出 List(Int64)
# ✅ 类型校验示例:检查是否为 list 类型
is_list_col = isinstance(schema["list_column"], pl.List)
print(is_list_col) # True
# ✅ 结合 dtype 选择器进行类型导向操作(推荐模式)
list_cols = df.select(pl.col(pl.List)) # 自动筛选所有 list 类型列
numeric_cols = df.select(pl.col(pl.NUMERIC_DTYPES)) # 筛选数值列
⚠️ 注意事项:
-
shrink_dtype()仅在 eager 模式下对 Series/DataFrame 生效(如df["list_column"].shrink_dtype()),返回的是优化后的 Series,不是类型对象,不可用于== pl.List比较; -
pl.List是类型构造器,需传入子类型(如pl.List(pl.Int64()))才构成完整类型;直接写pl.List是不完整类型,比较恒为False; - 若需在 LazyFrame 中做类型条件分支(如“若列为 list 则展开,否则保留”),应使用 Python 层逻辑预判 Schema,再构建对应表达式,而非在表达式内部“运行时判断类型”。
总结:Polars 的类型系统是静态、列级、编译期确定的。所有类型相关决策都应在查询构建前完成——通过 collect_schema() 获取类型元信息,再生成适配的表达式链。这是高效、安全且符合 Polars 设计哲学的最佳实践。










