
在 pandas `eval()` 中调用用户自定义函数时,需确保函数返回的是与 dataframe 兼容的 series(而非 python 原生 str),才能安全进行向量化字符串拼接;直接使用 `+` 操作符会失败,应改用 `.__add__()` 方法。
pandas 的 eval() 方法支持通过 @ 符号引用外部函数(如 @my_func),但其底层依赖于 pandas 的表达式引擎对 Series 的向量化操作。若自定义函数仅返回 Python 原生 str(例如 str(x) 作用于标量),eval() 会尝试将整个 Series 作为单个参数传入,导致隐式降维或类型不匹配——这正是你观察到 121\n142\n...additional string 这类混合输出的根本原因:数值部分被当作 Series 打印,而字符串字面量被追加到末尾。
✅ 正确做法是:让自定义函数返回一个 pd.Series(类型为 string 或 object),且长度与输入列一致。最简洁的方式是使用 .astype(str):
import pandas as pd
basic_df = pd.DataFrame({
"A": [1, 2, 3, 4, 5],
"B": [20, 40, 60, 100, 90],
"C": ["C1", "C2", "C3", "C4", "C5"],
})
def str_parse(series):
return series.astype(str) # ← 返回 str 类型的 Series,非单个字符串
# ✅ 正确:使用 __add__() 实现向量化字符串拼接
result = basic_df.eval("new_col = @str_parse(A + B + 100).__add__('additional string')")
print(result)输出:
A B C new_col 0 1 20 C1 121additional string 1 2 40 C2 142additional string 2 3 60 C3 163additional string 3 4 100 C4 204additional string 4 5 90 C5 195additional string
⚠️ 注意事项:
- ❌ 不要写 @str_parse(...) + "xxx":eval() 中的 + 在字符串上下文中默认触发 pd.Series.__radd__ 或类型推断逻辑,易出错;
- ✅ 必须用 .__add__('xxx'):显式调用 Series 的向量化字符串拼接方法,保证逐元素执行;
- ? 若需更灵活的格式化(如前缀/后缀/模板),推荐改用 assign() + map() 或 apply(),语义更清晰、调试更友好;
- ? 自定义函数中避免副作用(如打印、修改全局变量),eval() 可能多次调用或惰性求值。
总结:pandas.eval() 并非通用 Python 表达式求值器,而是面向向量化计算的 DSL。与其强行适配复杂字符串逻辑,不如在简单算术转换后切换至 assign(new_col=lambda df: ...) 链式调用——兼顾可读性、可维护性与性能。










