推荐的Python设计,用于捕获对类成员的更改

时间:2018-03-24 19:03:52

标签: python

我正在寻找适合Python的设计模式来解决以下问题:

假设某个成员Company有一个成员employees,这是一个包含任意数量Employee的列表。

我想要捕获的是当Employee的一个成员变量(假设salary)发生变化时,该变化会反映在“拥有”Company中(让我们看看)说total_salary)。我们还假设total_salary的计算成本非常高,我们只想在任何员工的薪水发生变化时进行计算,而不是每当我们将其作为财产进行访问时。

> c = Company()
> print(c.total_salary)
0
> c.employees.append(Employee())
> print(c.total_salary)
0
c.employees[0].salary = 100 # update total_salary for c now
> print(c.total_salary)
100

显而易见的方法是确保每个Employee都有一个引用回到它拥有的Company。我很好奇的是,是否有一种很好的方法可以在Company中使用getter,setter或其他内容,以确保我可以对salary中的任何元素进行employees更改,这样我就可以立即更新total_salary。至关重要的是,我们应该在更新其他成员时避免重新计算(例如name)。

3 个答案:

答案 0 :(得分:1)

class Company:
    def __init__(self, ....):
        self.employees = []
        self.total_salary = 0

    def add_employe(self, employe):
        self.employees.append(employe)
        self.total_salary += employe.salary

    def remove_employe(self, employe):
        self.employees.remove(employe)
        self.total_salary -= employe.salary

    def update_employe(self, employe):
        for e in self.employees:
            if not employe.id == e.id:
                continue
            e.name = employe.name
            # ... update more data here
            if employe.salary != e.salary: # salary suffered changes, update it
                self.total_salary -= e.salary        # subtract the older
                self.total_salary += employe.salary  # sum up the new
                e.salary = employe.salary            # update it


class Employee:
    _id = itertools.count(start=1)
    def __init__(self, ...):
        self.id = next(Employee._id)
        # ...

仅当total_salary遭受任何更改时才需要更新employe.salary。对此负责的是update_employe方法。 此外,某种idEmployee的实现也很有用。

答案 1 :(得分:0)

如果您正在寻找getter / setter控件,请查看Python property。您可以使用此模式来捕获何时设置变量,以实现自动更新功能。

答案 2 :(得分:0)

我认为有几种合理的方法可以做你所要求的。一种是让公司在每次请求时动态计算其总数。另一种方法是让Employee知道它所属的公司,并在公司自己的信息发生变化时更新公司的总数。

我认为第一种方法更容易,因为Employee实例不需要了解Company的任何内容,并且在更新Employee时不做任何特殊操作。缺点是,如果您的公司拥有许多员工并经常请求其总数,则可能会很慢,因为每次都需要遍历所有员工。以下是我使用property

实现它的方法
class Company:
    def __init__(self):
        self.employees = []

    @property
    def total_salary(self):
        return sum(e.salary for e in self.employees)

如果你采用第二种方法,你也可以使用property,但是你将它放在Employee类中,这样就可以检测到对{{1}的更改属性:

salary

要在更复杂的系统中完成这项工作,您可能需要一堆其他方法,例如添加class Company: def __init__(self): self.employees = [] self.total_salary = 0 class Employee: def __init__(self, employer): self.employer = employer self._salary = 0 @property def salary(self): return self._salary @salary.setter def salary(self, value): self.employer.total_salary += value - self._salary self._salary = value 并且工资已设置为Employee的方法(目前您必须首先将Company添加到公司,然后更新它的工资,否则总计将是错误的。