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

Python中如何实现自动为列表属性生成均值和标准差属性的装饰器

实现方案

你可以通过「自定义property标记类+元类」的方式实现需求,该方案会将自动生成的mean、std属性真实注入到类中,支持IDE自动补全,对原有代码侵入极小。

前置修正

首先修正你原有代码的小问题:calc_mean、calc_std方法需要接收待计算的列表作为入参,原定义缺少参数:

# 修正后的方法定义
def calc_mean(self, data: list[float]) -> float:
    # 你的均值计算逻辑
    pass

def calc_std(self, data: list[float]) -> float:
    # 你的标准差计算逻辑
    pass

完整实现代码

import statistics

# 自定义标记用property子类,不修改原生property的行为
class stat_property(property):
    pass

# 元类:类创建时自动扫描stat_property属性,注入对应的mean、std属性
class StatMeta(type):
    def __new__(cls, name, bases, attrs):
        # 收集所有被stat_property装饰的属性名
        stat_prop_names = [
            attr_name for attr_name, attr_val in attrs.items()
            if isinstance(attr_val, stat_property)
        ]

        # 为每个统计属性生成对应的mean、std只读property
        for prop_name in stat_prop_names:
            # 用默认参数prop=prop_name解决闭包延迟绑定问题
            def mean_getter(self, prop=prop_name):
                return self.calc_mean(getattr(self, prop))
            attrs[f"{prop_name}_mean"] = property(mean_getter)

            def std_getter(self, prop=prop_name):
                return self.calc_std(getattr(self, prop))
            attrs[f"{prop_name}_std"] = property(std_getter)

        return super().__new__(cls, name, bases, attrs)

# 你的Data类仅需要指定metaclass=StatMeta即可
class Data(metaclass=StatMeta):
    def __init__(self):
        self._list_a = [1.0, 2.0, 3.0, 4.0, 5.0]
        self._list_b = [2.0, 4.0, 6.0, 8.0, 10.0]

    def calc_mean(self, data: list[float]) -> float:
        return statistics.mean(data)

    def calc_std(self, data: list[float]) -> float:
        return statistics.stdev(data) if len(data) >= 2 else 0.0

    @stat_property
    def list_a(self) -> list[float]:
        return self._list_a

    @stat_property
    def list_b(self) -> list[float]:
        return self._list_b

使用效果测试

d = Data()
print(d.list_a) # 输出 [1.0, 2.0, 3.0, 4.0, 5.0]
print(d.list_a_mean) # 输出 3.0
print(d.list_a_std) # 输出 ~1.5811
print(d.list_b_mean) # 输出 6.0
print(d.list_b_std) # 输出 ~3.1623

轻量无元类实现(可选)

如果不想修改类的元类,可以用__getattr__的方式实现,无需改动类的继承结构,缺点是自动生成的属性不会被IDE自动补全:

import statistics

class Data:
    # 存储所有被stat_property装饰的属性名
    _stat_props = set()

    @classmethod
    def stat_property(cls, func):
        """自定义装饰器,标记属性同时收集名称"""
        prop = property(func)
        cls._stat_props.add(func.__name__)
        return prop

    def __init__(self):
        self._list_a = [1.0, 2.0, 3.0, 4.0, 5.0]
        self._list_b = [2.0, 4.0, 6.0, 8.0, 10.0]

    def calc_mean(self, data: list[float]) -> float:
        return statistics.mean(data)

    def calc_std(self, data: list[float]) -> float:
        return statistics.stdev(data) if len(data) >= 2 else 0.0

    def __getattr__(self, name: str):
        """访问不存在的属性时自动匹配mean、std规则"""
        if name.endswith("_mean"):
            base_prop = name[:-5]
            if base_prop in self._stat_props:
                return self.calc_mean(getattr(self, base_prop))
        elif name.endswith("_std"):
            base_prop = name[:-4]
            if base_prop in self._stat_props:
                return self.calc_std(getattr(self, base_prop))
        raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{name}'")

    @stat_property
    def list_a(self) -> list[float]:
        return self._list_a

    @stat_property
    def list_b(self) -> list[float]:
        return self._list_b

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 20:06:01