Python |避免重复代码块

时间:2017-10-08 13:34:19

标签: python python-3.x

我在一个控制虚拟机生命周期的类中有几个方法。开始,停止,终止,退休等操作

这些方法的代码几乎完全相同,例如:

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行代码并且它可以工作:)

2 个答案:

答案 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时传递方法方向。

对于额外的魔法(小心!),您也可以自动生成startstop等方法,因为它们都遵循相同的模式。