我在一个控制虚拟机生命周期的类中有几个方法。开始,停止,终止,退休等操作
这些方法的代码几乎完全相同,例如:
def stop(self, instances):
"""
Stop instance or a group of instances
:param instances: List of instances
:return:
"""
try:
response = self.ec2_client.stop_instances(InstanceIds=instances, DryRun=False)
print(response)
except ClientError as e:
print(e)
return response
def start(self, instances):
"""
Start instance or a group of instances
:param instances: List of instances
:return:
"""
try:
response = self.ec2_client.start_instances(InstanceIds=instances, DryRun=False)
print(response)
except ClientError as e:
print(e)
return response
如您所见,除了执行所需操作的API调用(start_instances和stop_instance)之外,这两种方法几乎完全相同。
是否有办法编写此类方法或函数,并防止重复代码?
提前致谢。
P.S。我在考虑装饰器,实例函数,闭包 - 但只是不知道如何!
以下答案激发了我对以下解决方案的启发:
@staticmethod
def _request_action_method(action, instances):
instance_ids = FleetManager._instance_to_str(instances)
def _action_method():
try:
response = action(InstanceIds=instance_ids, DryRun=False)
print(response)
except ClientError as e:
print(e)
return _action_method
我可以用这几行替换+50行代码并且它可以工作:)
答案 0 :(得分:2)
创建一个函数让我们说
@staticmethod
def _request(method, instances):
try:
response = method(InstanceIds=instances, DryRun=False)
print(response)
except ClientError as e:
print(e)
return response
并打电话给他们
def stop(self, instances):
self._request(self.ec2_client.stop_instances, instances)
def start(self, instances):
self._request(self.ec2_client.start_instances, instances)
答案 1 :(得分:1)
您可以存储stop: {stop_instances, start: start_instances}
的地图,并调用其他功能。使用getattr
按名称从self.ec2_client
获取成员,或仅使用整个方法。
伪代码:
在__init__
:
self.methodmap = {'start': self.ec2_client.start_instances,
'stop': self.ec2_client.stop_instances}
然后,例如:
def start(self, instances):
return self.run('start', instances)
def run(self, command, instances):
method = self.methodmap[command]
try:
response = method(InstanceIds=instances, DryRun=False)
print(response)
except ClientError as e:
print (e)
return response
根据您需要的灵活性,您不必定义self.methodmap
,也可以在调用self.run
时传递方法方向。
对于额外的魔法(小心!),您也可以自动生成start
,stop
等方法,因为它们都遵循相同的模式。