[PEAK] Computed sets
Adam Atlas
adam at atlas.st
Fri Mar 13 22:22:36 EDT 2009
I'm writing a module based on Trellis which provides several Set-like
objects, which can generally be used like Set or FrozenSet (plus the
Trellis .added and .removed attributes) but are generated dynamically
from some source sets, either by filtering one source set or by
applying some standard set operation (union, intersect, difference,
symmetric difference) to two source sets. The idea is to do this more
efficiently by watching for changes in the source sets and changing
the computed set appropriately, rather than having, say, a
trellis.compute(lambda self: self.set1.union(self.set2)), which would
require the whole set to be rebuilt any time set1 or set2 change at
all, and also wouldn't expose the .added and .removed attributes.
So here's how I'm doing it right now. Before I go further I just
thought I'd post it here to see if I'm on the right track, or if
there's anything wrong with this general approach.
class FilteredSubset(sets.BaseSet, trellis.Component):
source = trellis.make(trellis.Set, writable=True)
condition = trellis.attr(lambda self, val: True)
_data = trellis.Set._data
def __init__(self, source=None, condition=None, **kw):
trellis.Component.__init__(self, **kw)
if condition is not None:
self.condition = condition
if source is not None:
self.source = source
self._data.update((k, True) for k in source._data if
self.condition(k))
@trellis.compute
def added(self):
return set(k for k in self.source.added if self.condition(k))
@trellis.compute
def removed(self):
return set(k for k in self.source.removed if k in self)
class UnionSet(sets.BaseSet, trellis.Component):
source1 = trellis.make(trellis.Set, writable=True)
source2 = trellis.make(trellis.Set, writable=True)
_data = trellis.Set._data
def __init__(self, source1=None, source2=None, **kw):
trellis.Component.__init__(self, **kw)
if source1 is not None:
self.source1 = source1
self._data.update(dict.fromkeys(source1, True))
if source2 is not None:
self.source2 = source2
self._data.update(dict.fromkeys(source2, True))
@trellis.compute
def added(self):
'''
something is added to UnionSet if it is added to at least one
source
set and it was not already in either source set
'''
return self.source1.added.difference(self.source2).union(
self.source2.added.difference(self.source1))
@trellis.compute
def removed(self):
'''
something is removed from UnionSet if it is removed from both
source
sets, or if it is removed from one source set and it is not
in the
other source set
'''
return self.source1.removed.difference(self.source2).union(
self.source2.removed.difference(self.source1))
More information about the PEAK
mailing list