使用装饰器消除方法中对 if 语句的需要

Using decorators to eliminate need for if statements in methods

我有一个 class 存储文件中的一些数据,但有时该文件不存在。

class提供了多种方法对数据进行计算,但如果找不到数据,所有这些方法都会报错。​​

这是 class 和其中一种方法的示例:

class A:
    def __init__(self, file_name):
        if isfile(file_name):
            with open(file_name) as f:
                self.data = json.load(f)
        else:
            self.data = None

   def get_something(self):
       if self.data is None:
          raise ValueError('no data')

       return data['a'] + data['b']

问题 我怎样才能摆脱每个 class 方法中的 if 语句。有没有办法在 class 或方法级别使用装饰器,使其看起来比分散的 if 语句更好?

如果你想在方法级别有一个装饰器,定义一个包装函数并查看 self 参数以弄清楚 data 是什么:

def requires_data(a_method):
    def wrapped_method(self, *args, **kwargs):
        assert isinstance(self, A), "only use this decorator on A methods"
        if self.data is None:
            raise ValueError('no data')
        return a_method(self, *args, **kwargs)
    return wrapped_method


class A:
    def __init__(self, data):
        self.data = data

    @requires_data
    def get_something(self):
        return self.data['a'] + self.data['b']


print(A({'a': 21, 'b': 21}).get_something())
print(A(None).get_something())  # raises!

不过,如评论中所述,我宁愿将 data 设为必需属性,这样 __init__ 在不可用时立即引发:

class A:
    def __init__(self, data):
        if data is None:
            raise ValueError('no data')
        self.data = data

    def get_something(self):
        return self.data['a'] + self.data['b']


print(A({'a': 21, 'b': 21}).get_something())
print(A(None).get_something())  # raises!

如果 class 有一些功能依赖于 data 而有些不依赖,并且在某些情况下您只需要非 data 的功能,拆分class 沿着这些线分开。