蟒蛇。如何优化类集?

时间:2016-01-25 11:48:21

标签: python

我有以下内容:

class DepartmentsSet(ComplexModel):
    __namespace__ = MODELS_NS

    service_difference_set = Iterable(Department)
    db_difference_set = Iterable(Department)
    intersection_difference_set = Iterable(Department)

    def __init__(self, service_diff, db_diff, intersection):
        self.service_difference_set = _convert_to_departments(service_diff)
        self.db_difference_set = _convert_to_departments(db_diff)
        self.intersection_set = _convert_to_departments(intersection)


def _convert_to_departments(operation_set):
    departments = []
    for item in operation_set:
        department = dict(item)
        departments.append(Department(
            name=department.get('name'),
            external_id=department.get('external_id')
        ))


class EmployeesSet(ComplexModel):
    __namespace__ = MODELS_NS

    service_difference_set = Iterable(Employee)
    db_difference_set = Iterable(Employee)
    intersection_set = Iterable(Employee)

    def __init__(self, service_diff, db_diff, intersection):
        self.service_difference_set = _convert_to_employees(service_diff)
        self.db_difference_set = _convert_to_employees(db_diff)
        self.intersection_set = _convert_to_employees(intersection)


def _convert_to_employees(operation_set):
    employees = []
    for item in operation_set:
        employee = dict(item)
        dep = employee.get('department')
        employees.append(Employee(
            name=employee.get('name'),
            post=employee.get('post'),
            department=(dep.name if isinstance(dep, CompanyDepartment) else u''),
            contact_info=employee.get('contact_info'),
            external_id=employee.get('external_id')))
    return employees

我有两个问题:

  1. 因此,您可以看到我的课程DepartmentsSetEmployeesSet都具有相似的结构。它们之间的唯一区别是它们的集合由_convert_to_departments_convert_to_employees组成。 我意识到我的解决方案并不好。这种情况的最佳做法是什么?

  2. 有没有办法将函数_convert_to_departments_convert_to_employees统一为一般函数?

  3. *我不能为DepartmentsSet和EmployeesSet创建单个类,因为这些类将是我的SOAP服务的类型。

1 个答案:

答案 0 :(得分:2)

解决直接问题很简单 - 将公共代码和变量移动到超类并从中继承EmployeeSet和DepartmentSet:

class CommonModel(ComplexModel):

    def get_items(self, operation_set):
        items = [dict(x) for x in operation_set]
        return items

    # important: put COMMON methods, variables etc. here 

class DepartmentsSet(CommonModel):

    ...
    def _convert(self, operation_set):
        items = self.get_items(operation_set)
        for item in items:
            ... # convert to departments

class EmployeeSet(CommonModel):

    ...
    def _convert(self, operation_set):
        items = self.get_items(operation_set)
        for item in items:
            ... # convert to employees

然而,从策略上来说,我觉得这不是一个好的设计,如果它真的是“它们之间唯一的区别就是它们的集合由”组成,“DepartmentSetEmployeeSet真的不是同一件事情?你能不能把它变成一个有2个转换方法的类?

虽然这仍然不是很好的设计 - 你正在混合集合和类中的特定对象。这实际上违反了单一责任原则。将EmployeeDepartmentCommonModel设为一个类,只需将其实例放入列表中即可。如果你真的,真的需要转换某处提供单个对象转换方法,然后你可以做类似的事情:

[x.convert() for x in list_of_model_instances]

..甚至没有费心去检查x的类别(那是鸭子打字)。

我仍然认为你没有真正做过,它应该是一些其他的类或函数,可以在输入中使用CommonModel的实例,并用它做任何想做的事情。如果你真的需要进行精细的转换,为什么不创建一个Converter类,它可以接受许多输入实例并输出所要求的任何内容? (单一责任原则)

顺便说一句,如果你这样做,你可以使ComplexModel成为一个抽象基类或从中继承,如下所示:

class AbstractItemCheckpoint(object):
    __metaclass__ = ABCMeta

    '''Abstract item checkpoint, derive concrete item checkpoints that verify if a item (Subsystem, Component,
       etc.) is eligible for creating a Task for it.'''

    @abstractmethod
    def convert(self):
        '''
        Ensure that model inheriting from AbstractItemCheckpoint has convert method.
        '''
        pass

这可以确保EmployeeDepartment等任何类都必须使用convert方法,从而使提交到Converter的实例更安全。