不使用闭包实现Data类链式where过滤API的替代方案
方案1:结构化操作栈实现(完全无闭包)
这个思路的核心是把Expr的每一步操作换成操作类型+参数的结构化数据存储,而不是存lambda闭包,执行逻辑统一放在求值方法里实现,完全避免匿名函数的使用:
from __future__ import annotations from typing import Dict, Any, Tuple, List import numpy as np class Data: def __init__(self, data: Dict): self._data = data def where(self, e: Expr) -> Data: idx = e.eval(self) for k,v in self._data.items(): self._data[k] = v[idx] return self def __repr__(self): return str(self._data) class Expr: def __init__(self): # 操作栈存储(操作类型, 参数),完全不存储闭包/匿名函数 self._ops: List[Tuple[str, Any]] = [] def col(self, s: str) -> Expr: self._ops.append(("get_column", s)) return self def equals(self, el: Any) -> Expr: self._ops.append(("equal_compare", el)) return self def eval(self, data_inst: Data) -> np.ndarray: current_val = None for op_type, op_param in self._ops: if op_type == "get_column": current_val = data_inst._data[op_param] elif op_type == "equal_compare": current_val = current_val == op_param # 后续要扩展大于、小于、四则运算等操作,只需要新增分支即可 return current_val def col(s: str) -> Expr: return Expr().col(s)
这个方案没有任何闭包相关的逻辑,所有执行规则都是显式定义的,更容易调试和序列化,非常适合轻量过滤场景。
方案2:表达式树实现(可扩展复杂语法)
如果你需要支持更自然的调用语法(比如直接写col("a") == 3代替.equals(3)),可以用多态表达式节点的方案,也是Spark、Polars等大数据框架内部DSL的标准实现思路,同样不需要闭包:
from __future__ import annotations from typing import Dict import numpy as np class Data: def __init__(self, data: Dict): self._data = data def where(self, e: ExprNode) -> Data: idx = e.eval(self) for k,v in self._data.items(): self._data[k] = v[idx] return self def __repr__(self): return str(self._data) # 表达式节点基类 class ExprNode: def eval(self, data: Data): raise NotImplementedError # 取列节点 class ColNode(ExprNode): def __init__(self, col_name: str): self.col_name = col_name def eval(self, data: Data): return data._data[self.col_name] # 重载运算符实现更自然的语法 def __eq__(self, other) -> ExprNode: return EqualNode(self, other) def __gt__(self, other) -> ExprNode: return GreaterNode(self, other) # 相等比较节点 class EqualNode(ExprNode): def __init__(self, left: ExprNode, right: Any): self.left = left self.right = right def eval(self, data: Data): return self.left.eval(data) == self.right # 大于比较节点 class GreaterNode(ExprNode): def __init__(self, left: ExprNode, right: Any): self.left = left self.right = right def eval(self, data: Data): return self.left.eval(data) > self.right def col(s: str) -> ColNode: return ColNode(s) # 调用时可以直接写成更符合直觉的语法 # data = Data(inpt).where(col("a") == 3)
这个方案支持任意复杂的表达式嵌套组合,扩展性极强,适合需要构建复杂查询逻辑的场景。
内容的提问来源于stack exchange,提问作者FredMaster
相关产品推荐
相关产品推荐

