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

如何通过属性函数动态为类添加方法,实现类似SQLAlchemy relationship的效果

实现方案

你要的功能可以通过Python的描述符协议实现,Python 3.6以上版本新增的__set_name__方法可以直接拿到属性所属的类和属性名,完全符合你的需求,不需要提前预知类和属性信息,和SQLAlchemy relationship()的实现思路一致。

方案1:基于__set_name__(推荐,Python 3.6+)

这是最简实现,不需要元类或者父类继承:

class GetterDescriptor:
    def __init__(self, default=None):
        self.default = default
        # 存储属性名和生成的getter方法名,__set_name__调用时赋值
        self.attr_name = None
        self.getter_name = None

    def __set_name__(self, owner, name):
        # 类创建时自动调用,owner为所属类,name为属性绑定的变量名
        self.attr_name = name
        self.getter_name = f"get_{name}"
        
        # 动态为类添加get_xxx方法
        def getter(self):
            # 这里可以替换为你需要的复杂逻辑,比如get_contact的业务逻辑
            return getattr(self, f"_{self.attr_name}", self.default)
        
        setattr(owner, self.getter_name, getter)

    def __get__(self, instance, owner):
        if instance is None:
            return self
        return getattr(instance, f"_{self.attr_name}", self.default)

    def __set__(self, instance, value):
        # 赋值时将值存在实例的私有属性中,避免和描述符本身冲突
        setattr(instance, f"_{self.attr_name}", value)

# 你需要的工具函数
def create_get_method(default=None):
    return GetterDescriptor(default=default)

调用效果和你的需求完全匹配:

class SomeClass:
    example = create_get_method(default="初始默认值")

obj = SomeClass()
print(obj.get_example()) # 输出:初始默认值
obj.example = "自定义值"
print(obj.get_example()) # 输出:自定义值
print(obj.example) # 输出:自定义值

方案2:基于元类(兼容Python 3.6以下版本)

如果需要兼容旧版本Python,可以用元类在类创建阶段扫描属性生成方法:

class GetterMeta(type):
    def __new__(cls, name, bases, attrs):
        for attr_name, attr_val in attrs.items():
            # 识别标记了需要生成getter的属性
            if getattr(attr_val, "_is_getter_target", False):
                getter_name = f"get_{attr_name}"
                # 生成对应的getter方法
                def getter(self, attr=attr_name):
                    # 替换为你的业务逻辑
                    return getattr(self, attr)
                attrs[getter_name] = getter
        return super().__new__(cls, name, bases, attrs)

def create_get_method():
    # 生成带标记的占位对象,供元类识别
    placeholder = object()
    setattr(placeholder, "_is_getter_target", True)
    return placeholder

调用示例:

class SomeClass(metaclass=GetterMeta):
    example = create_get_method()
    
    def __init__(self):
        self.example = "测试值"

obj = SomeClass()
print(obj.get_example()) # 输出:测试值

原理解释

SQLAlchemy的relationship()本质上也是基于描述符协议实现:返回一个描述符实例,在类创建阶段拿到属性名和所属类信息,之后动态生成关联查询的访问逻辑,和上述实现的核心思路完全一致。

内容的提问来源于stack exchange,提问作者Cyril N.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 13:18:04