运行 class 的每个方法之后修改实例变量的最佳方法?
Best approach to modify instance variable after running each method of a class?
我正在 Python 开发数据分析应用程序。我有一个 DataAttributes
class 提供数据集的各种细节。然而,在获取其中一些值时,它使用了另一组直接修改数据的方法——我的DataManipulator
class。
为了简化向每个 class 添加未来方法的事情,我希望能够在 运行 来自 DataAttributes
的方法之后将数据集重置为其原始状态。所以这涉及:
- 存储数据集的初始状态
- 运行 来自
DataAttributes
类型实例的方法
- 正在将数据集重置为初始状态
当然我可以通过 运行 在每个 DataAttributes
方法的开头和结尾添加一个方法来完成此操作,但这感觉非常笨拙,尤其是考虑到有许多获取数据的方法属性。实现这个的干净方法是什么?我研究过制作元 class,但不确定如何使用该方法修改实例变量。我也研究过装饰器,但我也不确定那是否最好。
就我想要实现的示例而言,我想执行下面的操作,但对于 "n" 方法。此外,这是对我正在做的事情的极大简化——让我们假装我对我正在做的事情有充分的理由,我知道从概念上讲,这个例子没有什么意义。这只是为了展示我想要实现的目标。
class MyClass():
def __init__(self):
self.mydata = np.array([1, 2, 3])
self.my_initial_data = np.array([1, 2, 3])
def store_initial_data(self):
self.my_initial_data = np.array([1, 2, 3])
def reset_data(self):
self.mydata = self.my_initial_data
print(self.mydata)
def method_1(self):
self.store_initial_data()
self.mydata *= 2
self.reset_data()
def method_2(self):
self.store_initial_data()
self.mydata *= 2
self.reset_data()
.
.
.
def method_n(self):
self.store_initial_data()
self.mydata *= 2
self.reset_data()
my_inst = MyClass()
my_inst.method_1() # prints [1, 2, 3]
我认为自定义属性访问是最简单的事情,这样当从实例中检索方法时,它被包装在代码中,该代码将执行
设置和清理任务。
如果你的方法只有一个模式,这样它们就可以被识别,它就会变得万无一失。在下面的示例中,我为从实例中检索到的每个可调用对象执行此操作,除非其名称以 _
开头 - 这将避免使用特殊方法,并且您不想包装的任何方法都可以以 _
.
这个解决方案只需要一个基类——不需要元类:
def wrap(method, prefix, postfix):
def wrapper(*args, **kw):
prefix(*args, **kw)
result = method(*args, **kw)
postfix(*args, **kw)
return result
return wrapper
class SetupCleanupBase:
def __getattribute__(self, name):
attr = super().__getattribute__(name)
if not name.startswith("_") and callable(attr):
attr = wrap(attr, self._setup, self._cleanup)
return attr
class MyClass(SetupCleanupBase):
...
def _setup(self):
self.my_initial_data = np.array([1, 2, 3])
def _cleanup(self):
self.mydata = self.my_initial_data
print(self.mydata)
我正在 Python 开发数据分析应用程序。我有一个 DataAttributes
class 提供数据集的各种细节。然而,在获取其中一些值时,它使用了另一组直接修改数据的方法——我的DataManipulator
class。
为了简化向每个 class 添加未来方法的事情,我希望能够在 运行 来自 DataAttributes
的方法之后将数据集重置为其原始状态。所以这涉及:
- 存储数据集的初始状态
- 运行 来自
DataAttributes
类型实例的方法
- 正在将数据集重置为初始状态
当然我可以通过 运行 在每个 DataAttributes
方法的开头和结尾添加一个方法来完成此操作,但这感觉非常笨拙,尤其是考虑到有许多获取数据的方法属性。实现这个的干净方法是什么?我研究过制作元 class,但不确定如何使用该方法修改实例变量。我也研究过装饰器,但我也不确定那是否最好。
就我想要实现的示例而言,我想执行下面的操作,但对于 "n" 方法。此外,这是对我正在做的事情的极大简化——让我们假装我对我正在做的事情有充分的理由,我知道从概念上讲,这个例子没有什么意义。这只是为了展示我想要实现的目标。
class MyClass():
def __init__(self):
self.mydata = np.array([1, 2, 3])
self.my_initial_data = np.array([1, 2, 3])
def store_initial_data(self):
self.my_initial_data = np.array([1, 2, 3])
def reset_data(self):
self.mydata = self.my_initial_data
print(self.mydata)
def method_1(self):
self.store_initial_data()
self.mydata *= 2
self.reset_data()
def method_2(self):
self.store_initial_data()
self.mydata *= 2
self.reset_data()
.
.
.
def method_n(self):
self.store_initial_data()
self.mydata *= 2
self.reset_data()
my_inst = MyClass()
my_inst.method_1() # prints [1, 2, 3]
我认为自定义属性访问是最简单的事情,这样当从实例中检索方法时,它被包装在代码中,该代码将执行 设置和清理任务。
如果你的方法只有一个模式,这样它们就可以被识别,它就会变得万无一失。在下面的示例中,我为从实例中检索到的每个可调用对象执行此操作,除非其名称以 _
开头 - 这将避免使用特殊方法,并且您不想包装的任何方法都可以以 _
.
这个解决方案只需要一个基类——不需要元类:
def wrap(method, prefix, postfix):
def wrapper(*args, **kw):
prefix(*args, **kw)
result = method(*args, **kw)
postfix(*args, **kw)
return result
return wrapper
class SetupCleanupBase:
def __getattribute__(self, name):
attr = super().__getattribute__(name)
if not name.startswith("_") and callable(attr):
attr = wrap(attr, self._setup, self._cleanup)
return attr
class MyClass(SetupCleanupBase):
...
def _setup(self):
self.my_initial_data = np.array([1, 2, 3])
def _cleanup(self):
self.mydata = self.my_initial_data
print(self.mydata)