我的类(dataclass)有许多基于其他属性或dataclass个字段计算的属性.

我正在try 创建一个decorator,它获取所需字段或属性的列表.这意味着他们不能是None岁,也不能返回ValueError岁.如果其中任何一个是None,那么我想做点什么-为了简单起见,让我们raise ValueError(f'Missing {fieldname}').

def required_fields(required_fields):
    def _required_fields(f):
        def wrapper(self, *args, **kwargs):
            for field in required_fields:
                if getattr(self, field) is None:
                    raise ValueError(f"Missing {field}")
            return f
        return wrapper
    return _required_fields

编辑-再次try

def required_fields(required_fields):
    def _required_fields(f):
        @functools.wraps(f)
        def wrapper(self, *args, **kwargs):
            for field in required_fields:
                if getattr(self, field) is None:
                    raise ValueError(f"Missing {field}")
            return f(self, *args, **kwargs)
        return wrapper

Usage

@dataclasses.dataclass
class LoanCalculator:
    _amount: typing.Optional[M] = None
    _interest_rate: typing.Optional[M] = None
    _years: typing.Optional[M] = None
    _balance: typing.Optional[M] = None
    _payment_day: typing.Optional[int] = None
    _start_date: typing.Optional[datetime.date] = None

    class MissingDataError(Exception):
        pass

    @required_fields(['_interest_rate'])
    @property
    def monthly_interest_rate(self):
        return self._interest_rate / 12

我想在None时得到ValueError(f'Missing _interest_rate'),然后打monthly_interest_rate.

问题是根本没有调用包装器,我不知道如何继续.你能给我一些提示吗?

推荐答案

看起来这就是你想要的:

from dataclasses import dataclass


def required_fields(fields):
    def wrapper(fun):
        def checker(self):
            for field in fields:
                if not hasattr(self, field):
                    raise AttributeError(f'Missing field {field}')
                if getattr(self, field) is None:
                    raise ValueError(f'Field {field} is `None`')
            return fun(self)
        return checker
    return wrapper


@dataclass
class LoanCalculator:
    _interest_rate: int = None

    def set_interest_rate(self, value):
        self._interest_rate = value

    @property
    @required_fields(['_interest_rate'])
    def monthly_interest_rate(self):
        return self._interest_rate / 12


lc = LoanCalculator()
try:
    print(lc.monthly_interest_rate)
except ValueError:
    print('This exception is expected')

lc.set_interest_rate(.5)  # after this, lc._intereste_rate is no longer None
print(lc.monthly_interest_rate)
print('No exception here')

此decorator 判断传递给方法的对象(碰巧是属性设置器)是否具有必需的属性,并且其值不是None.

输出:

This exception is expected
0.041666666666666664
No exception here

这里您的问题的答案可能是:"您应该将@property放在@required\u fields decorator之前,而不是之后"

Python相关问答推荐

从包含数字和单词的文件中读取和获取数据集

如何使用矩阵在sklearn中同时对每个列执行matthews_corrcoef?

有症状地 destruct 了Python中的regex?

处理带有间隙(空)的duckDB上的重复副本并有效填充它们

如何让Flask 中的请求标签发挥作用

如何让程序打印新段落上的每一行?

Python中绕y轴曲线的旋转

如何使用pytest来查看Python中是否存在class attribution属性?

在vscode上使用Python虚拟环境时((env))

如何更改groupby作用域以找到满足掩码条件的第一个值?

跳过嵌套JSON中的级别并转换为Pandas Rame

以异步方式填充Pandas 数据帧

从源代码显示不同的输出(机器学习)(Python)

使用Python TCP套接字发送整数并使用C#接收—接收正确数据时出错

BeatuifulSoup从欧洲志愿者服务中获取数据和解析:一个从EU-Site收集机会的小铲子

用0填充没有覆盖范围的垃圾箱

大型稀疏CSR二进制矩阵乘法结果中的错误

如何在Polars中创建条件增量列?

我怎样才能让深度测试在OpenGL中使用Python和PyGame呢?

将数据从一个单元格保存到Jupyter笔记本中的下一个单元格