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

Python中替代传引用实现DRY 解决基类方法更新指针不生效问题

核心问题原因

Python 中所有参数传递都是传对象引用,对形参直接赋值(ptr_to_object = new_widget)只是将形参变量重新绑定到新对象,不会修改外部传入的原始变量/实例属性的值,这是语言的核心设计特性。


符合DRY原则的解决方案

方案1:返回值回写(最简洁,无额外依赖)

修改基类方法将处理后的widget返回,子类调用时直接赋值给自身属性,实现逻辑复用的同时完成属性更新。

class BaseWindow:
    def do_common_task(self, new_widget: QWidget) -> QWidget:
        # 原有对new_widget的通用处理逻辑保留
        return new_widget

class WindowA(BaseWindow):
    ptr_to_obj: QWidget
    something_widget: Something
    something_else_widget: SomethingElse

    def __init__(self) -> None:
        self.ptr_to_obj = None
        self.something_widget = None
        self.something_else_widget = None

    def switch_obj_value(self) -> None:
        self.something_widget = Something()
        self.ptr_to_obj = self.do_common_task(self.something_widget)

    def switch_another_obj_value(self) -> None:
        self.something_else_widget = SomethingElse()
        self.ptr_to_obj = self.do_common_task(self.something_else_widget)

方案2:传属性名+setattr(适合需要修改实例任意属性的场景)

如果需要修改的实例属性不固定,可以将属性名作为字符串传入基类方法,通过setattr直接修改实例的属性值,无需额外包装。

class BaseWindow:
    def do_common_task(self, attr_name: str, new_widget: QWidget) -> None:
        # 原有对new_widget的通用处理逻辑保留
        setattr(self, attr_name, new_widget)

class WindowA(BaseWindow):
    # 其余属性、初始化代码保持不变
    def switch_obj_value(self) -> None:
        self.something_widget = Something()
        self.do_common_task("ptr_to_obj", self.something_widget)

    def switch_another_obj_value(self) -> None:
        self.something_else_widget = SomethingElse()
        self.do_common_task("ptr_to_obj", self.something_else_widget)

方案3:可变对象包装(即自定义指针类方案)

如果需要传递类似“指针引用”的效果,可以把要修改的值包装在一个可变容器中(自定义类、列表、字典都可以),修改容器内的元素会同步到外部。

from dataclasses import dataclass
from typing import Generic, TypeVar

T = TypeVar('T')

@dataclass
class Ptr(Generic[T]):
    value: T

class BaseWindow:
    def do_common_task(self, ptr: Ptr[QWidget], new_widget: QWidget) -> None:
        # 原有对new_widget的通用处理逻辑保留
        ptr.value = new_widget

class WindowA(BaseWindow):
    ptr_to_obj: Ptr[QWidget]
    # 其余属性保持不变

    def __init__(self) -> None:
        self.ptr_to_obj = Ptr(value=None)
        self.something_widget = None
        self.something_else_widget = None

    def switch_obj_value(self) -> None:
        self.something_widget = Something()
        self.do_common_task(self.ptr_to_obj, self.something_widget)
        # 此时self.ptr_to_obj.value已经被更新为新的widget

三种方案通用逻辑全部保留在基类中,完全符合DRY原则,可根据业务场景选择:仅需要更新固定属性优先选方案1;需要动态修改不同实例属性选方案2;确实需要指针传递语义选方案3。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 22:48:03