You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何延迟传入Python类__init__的表达式求值至__call__调用时

实现方案

核心思路是让重载的逻辑运算符不直接返回布尔值结果,而是返回封装了运算关系的可调用对象,把实际求值动作推迟到调用阶段传入运行时参数时再执行。


具体实现步骤

1. 定义逻辑组合节点

先实现一个通用的组合节点类,用来保存运算符两侧的操作数和运算类型,统一实现延迟调用接口:

from typing import Callable, Any

class _AuthOpNode:
    def __init__(self, left: Callable, op_type: str, right: Callable):
        self.left = left
        self.op_type = op_type
        self.right = right

    def __call__(self, *runtime_args, **runtime_kwargs) -> bool:
        left_result = self.left(*runtime_args, **runtime_kwargs)
        # 保留原生逻辑运算符的短路特性
        if self.op_type == "or":
            return left_result or self.right(*runtime_args, **runtime_kwargs)
        if self.op_type == "and":
            return left_result and self.right(*runtime_args, **runtime_kwargs)
        raise ValueError(f"不支持的运算类型: {self.op_type}")

2. 改造Auth基类

把原来直接执行权限判断的运算符重载改成返回组合节点,同时让Auth实例本身和组合节点保持一致的可调用接口:

class Auth:
    def __init__(self, config_val: str):
        self.config_val = config_val

    def has_perm(self, runtime_arg: Any) -> bool:
        raise NotImplementedError("具体子类实现实际权限判断逻辑")

    def __call__(self, *runtime_args, **runtime_kwargs) -> bool:
        return self.has_perm(*runtime_args, **runtime_kwargs)

    def __or__(self, other: Callable) -> _AuthOpNode:
        return _AuthOpNode(self, "or", other)

    def __and__(self, other: Callable) -> _AuthOpNode:
        return _AuthOpNode(self, "and", other)

3. 实现IsAllowed类

初始化阶段只保存传入的表达式对象,不做任何求值,等到__call__执行时再传入运行时参数触发实际判断:

class IsAllowed:
    def __init__(self, classes: list[Callable]):
        self.check_list = classes

    def __call__(self, runtime_arg: Any) -> bool:
        # 此处可根据业务需求调整判断逻辑,示例为列表内任意规则通过即返回True
        for check in self.check_list:
            if check(runtime_arg):
                return True
        return False

使用效果

完全匹配期望的调用接口,初始化阶段不会执行任何权限校验逻辑:

# 实现具体的校验子类
class Auth1(Auth):
    def has_perm(self, runtime_arg):
        print(f"Auth1执行校验,配置值:{self.config_val},运行时参数:{runtime_arg}")
        return runtime_arg.get("allow_auth1", False)

class Auth2(Auth):
    def has_perm(self, runtime_arg):
        print(f"Auth2执行校验,配置值:{self.config_val},运行时参数:{runtime_arg}")
        return runtime_arg.get("allow_auth2", False)

# 初始化时仅构建表达式树,无实际校验动作
permission_checker = IsAllowed(classes=[Auth1('some_value') | Auth2('some_other_value')])

# 调用阶段传入运行时参数才会执行实际校验,自动保留短路逻辑
final_result = permission_checker({"allow_auth1": True})
# 输出:Auth1执行校验,配置值:some_value,运行时参数:{'allow_auth1': True}
# final_result值为True,且不会触发Auth2的校验

扩展说明

  • 该方案支持任意层级的逻辑嵌套,比如Auth1('a') | Auth2('b') & Auth3('c')会自动生成嵌套的运算节点,调用时递归求值即可
  • 如果需要支持非运算,只要在Auth类中添加__invert__方法,返回对应取反逻辑的运算节点即可
  • 所有逻辑判断保留原生运算符的短路特性,不会执行不必要的校验逻辑

内容的提问来源于stack exchange,提问作者Amir Afianian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 22:48:26