Python Module Exposure

George Sakkis gsakkis at rutgers.edu
Sat Jul 9 14:47:31 EDT 2005


"Jacob Page" <apoco at cox.net> wrote:

> George Sakkis wrote:
> > There are several possible use cases where dealing directly with
> > intervals would be appropriate or necessary, so it's good to have them
> > supported directly by the module.
>
> I think I will keep Interval exposed.  It sort of raises a bunch of
> hard-to-answer design questions having two class interfaces, though.
> For example, would Interval.between(2, 3) + Interval.between(5, 7) raise
> an error (as it currently does) because the intervals are disjoint or
> yield an IntervalSet, or should it not even be implemented?  How about
> subtraction, xoring, and anding?  An exposed class should have a more
> complete interface.
>
> I think that IntervalSet.between(5, 7) | IntervalSet.between(2, 3) is
> more intuitive than IntervalSet(Interval.between(5, 7),
> Interval.between(2, 3)), but I can understand the reverse.  I think I'll
> just support both.

As I see it, there are two main options you have:

1. Keep Intervals immutable and pass all the responsibility of
combining them to IntervalSet. In this case Interval.__add__ would have
to go. This is simple to implement, but it's probably not the most
convenient to the user.

2. Give Interval the same interface with IntervalSet, at least as far
as interval combinations are concerned, so that Interval.between(2,3) |
Interval.greaterThan(7) returns an IntervalSet. Apart from being user
friendlier, an extra benefit is that you don't have to support
factories for IntervalSets, so I am more in favor of this option.

Another hard design problem is how to combine intervals when
inheritance comes to play. Say that you have FrozenInterval and
FrozenIntervalSet subclasses. What should "Interval.between(2,3) |
FrozenInterval.greaterThan(7)" return ? I ran into this problem for
another datastructure that I wanted it to support both mutable and
immutable versions. I was surprised to find out that:
>>> s1 = set([1])
>>> s2 = frozenset([2])
>>> s1|s2 == s2|s1
True
>>> type(s1|s2) == type(s2|s1)
False

It make sense why this happens if you think about the implementation,
but I guess most users expect the result of a commutative operation to
be independent of the operands' order. In the worst case, this may lead
to some hard-to-find bugs.

George




More information about the Python-list mailing list