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

Python 3.11下YAML补丁类继承的优化实现问询

优化YAML补丁类的实现方案(Python 3.11)

针对你遇到的代码重复、参数混淆、维护成本高的问题,以下是几种贴合需求的高效实现方案,完全符合DRY原则,且调用简洁易记。


方案1:类变量+重载__call__(适合单动态参数,无关键字混淆)

核心思路:父类封装通用补丁构建逻辑,子类仅定义静态默认值,通过重载__call__接收固定位置的动态参数,彻底避免关键字参数的记忆负担。

from typing import Dict, List, Any

class YamlPatch:
    # 全局默认值,子类可按需覆盖
    kind: str = "test"
    namespace: str = "my-namespace"
    op: str = "replace"
    name: str = ""
    path: str = ""
    value: str = ""

    @classmethod
    def _build_patch(cls, **override) -> tuple[Dict[str, Any], List[Dict[str, Any]]]:
        """通用补丁构建逻辑,合并类默认值与动态覆盖值"""
        target = {
            "kind": override.get("kind", cls.kind),
            "name": override.get("name", cls.name),
            "namespace": override.get("namespace", cls.namespace)
        }
        scalar = [{
            "op": override.get("op", cls.op),
            "path": override.get("path", cls.path),
            "value": override.get("value", cls.value)
        }]
        return (target, scalar)

    @classmethod
    def __call__(cls) -> tuple[Dict[str, Any], List[Dict[str, Any]]]:
        """默认调用逻辑,适用于纯静态补丁"""
        return cls._build_patch()

# 示例1:仅name为动态参数的补丁
class PatchA(YamlPatch):
    path = "/test"
    value = "hello"

    @classmethod
    def __call__(cls, name: str) -> tuple[Dict[str, Any], List[Dict[str, Any]]]:
        return cls._build_patch(name=name)

# 示例2:仅path为动态参数的补丁
class PatchB(YamlPatch):
    name = "my-name"
    value = "hello"

    @classmethod
    def __call__(cls, path: str) -> tuple[Dict[str, Any], List[Dict[str, Any]]]:
        return cls._build_patch(path=path)

# 示例3:纯静态补丁
class AppsGitRepoBranchPatch(YamlPatch):
    kind = "GitRepository"
    name = "app-repo"
    path = "/spec/ref/branch"
    value = "my-branch-name"

# 使用方式
patches = []
patches.append(PatchA("hello"))  # 直接传位置参数,无需关键字
for app in ["app1", "app2"]:
    patches.append(PatchB(f"/{app}"))
patches.append(AppsGitRepoBranchPatch())  # 纯静态补丁直接调用类

print(patches)

方案优势

  • 完全符合DRY原则:父类封装所有通用逻辑,子类仅需定义差异的静态值和动态参数处理
  • 无参数混淆:每个补丁的__call__仅接收固定位置的动态参数,无需记忆关键字
  • 易维护:静态默认值集中在类变量,修改一处即可同步所有实例
  • 调用简洁:动态补丁直接传位置参数,静态补丁直接调用类即可

方案2:模板占位符(适合多动态参数)

如果补丁需要多个动态参数,可使用字符串模板占位符,通过关键字参数传递动态值,参数名与模板占位符一一对应,降低记忆成本。

from typing import Dict, List, Any

class YamlPatch:
    kind: str = "test"
    namespace: str = "my-namespace"
    op: str = "replace"
    name: str = ""
    path: str = ""
    value: str = ""

    @classmethod
    def _resolve_template(cls, **kwargs) -> Dict[str, Any]:
        """解析类变量中的模板占位符,替换为动态参数"""
        resolved = {}
        for attr in ["kind", "name", "namespace", "op", "path", "value"]:
            val = getattr(cls, attr)
            if isinstance(val, str):
                resolved[attr] = val.format(**kwargs)
            else:
                resolved[attr] = val
        # 用户传入的参数优先级高于模板解析结果
        resolved.update(kwargs)
        return resolved

    @classmethod
    def __call__(cls, **kwargs) -> tuple[Dict[str, Any], List[Dict[str, Any]]]:
        resolved = cls._resolve_template(**kwargs)
        target = {k: resolved[k] for k in ["kind", "name", "namespace"]}
        scalar = [{k: resolved[k] for k in ["op", "path", "value"]}]
        return (target, scalar)

# 示例:需要application动态参数的补丁
class PackageApplicationFromGit(YamlPatch):
    kind = "Package"
    namespace = "apps"
    op = "replace"
    path = "/spec/path"
    name = "application-{application}"
    value = "/some/applications/path/{application}"

# 使用方式
patches = []
patches.append(PackageApplicationFromGit(application="my-app"))
# 支持直接覆盖静态值
patches.append(PackageApplicationFromGit(application="test-app", namespace="test-namespace"))

方案优势

  • 支持多动态参数:通过模板占位符关联参数名,清晰直观
  • 灵活扩展:可直接传入关键字参数覆盖任意静态值
  • 维护成本低:静态模板集中在类变量,修改模板即可同步所有调用

方案3:直接类属性输出纯静态补丁

对于完全无动态参数的补丁,可直接在类中定义yaml属性,无需调用类实例:

class YamlPatch:
    @classmethod
    @property
    def yaml(cls) -> tuple[Dict[str, Any], List[Dict[str, Any]]]:
        return (
            {"kind": cls.kind, "name": cls.name, "namespace": cls.namespace},
            [{"op": cls.op, "path": cls.path, "value": cls.value}]
        )

class StaticBranchPatch(YamlPatch):
    kind = "GitRepository"
    name = "app-repo"
    namespace = "my-namespace"
    op = "replace"
    path = "/spec/ref/branch"
    value = "my-branch-name"

# 使用方式
print(StaticBranchPatch.yaml)

方案优势

  • 极致简洁:纯静态补丁直接通过类属性访问,无需任何调用
  • 零冗余:完全避免实例化操作,性能最优

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 14:08:14