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

Ger*_*ges 1 python metaclass decorator

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

该类提供了多种方法来对数据进行计算,但如果没有找到数据,所有这些方法都会引发错误。

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

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']
Run Code Online (Sandbox Code Playgroud)

问题 如何摆脱每个类方法中的 if 语句。有没有办法在类或方法级别使用装饰器,这使得它看起来比分散的 if 语句更好?

Sam*_*ord 6

如果您想在方法级别有一个装饰器,请定义一个包装函数并查看参数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!
Run Code Online (Sandbox Code Playgroud)

不过,正如评论中所指出的,我更倾向于将其作为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!
Run Code Online (Sandbox Code Playgroud)

如果类具有一些依赖的功能data和一些不依赖的功能,并且在某些情况下您只需要非data功能,请沿着这些线将类分开。