class Environment:
    def __init__(self, parent=None, propagate_assignments=True):
        self.parent = parent
        self.propagate_assignments = propagate_assignments
        self.values = {}

    def define(self, name, value):
        self.values[name] = value

    def contains(self, name):
        if name in self.values:
            return True
        if self.parent is None:
            return False
        return self.parent.contains(name)

    def get(self, name):
        if name in self.values:
            return self.values[name]
        if self.parent is not None:
            return self.parent.get(name)
        raise KeyError(name)

    def assign(self, name, value):
        if name in self.values:
            self.values[name] = value
            return

        if (
            self.propagate_assignments
            and self.parent is not None
            and self.parent.contains(name)
        ):
            self.parent.assign(name, value)
            return

        self.values[name] = value
