使用装饰器消除方法中对 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 沿着这些线分开。
我有一个 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 沿着这些线分开。