Python Module Exposure

Jacob Page apoco at cox.net
Sat Jul 9 13:17:06 EDT 2005


George Sakkis wrote:
> "Jacob Page" <apoco at cox.net> wrote:
> 
>>George Sakkis wrote:
>>
>>>1. As already noted, ISet is not really descriptive of what the class
>>>does. How about RangeSet ? It's not that long and I find it pretty
>>>descriptive. In this case, it would be a good idea to change Interval
>>>to Range to make the association easier.
>>
>>The reason I decided not to use the term Range was because that could be
>>confused with the range function, which produces a discrete set of
>>integers.  Interval isn't a term used in the standard/built-in library,
>>AFAIK, so I may stick with it.  Is this sound reasoning?
> 
> Yes, it is not unreasonable; I can't argue strongly against Interval.
> Still I'm a bit more in favor of Range and I don't think it is
> particularly confusing with range() because:
> 1. Range has to be either qualified with the name of the package (e.g.
> rangesets.Range) or imported as "from rangesets import Range", so one
> cannot mistake it for the range builtin.
> 2. Most popular naming conventions use lower first letter for functions
> and capital for classes.
> 3. If you insist that only RangeSet should be exposed from the module's
> interface and Range (Interval) should be hidden, the potential conflict
> between range() and RangeSet is even less.

Those are pretty good arguments, but after doing some poking around on 
planetmath.org and reading 
http://planetmath.org/encyclopedia/Interval.html, I've now settled on 
Interval, since that seems to be the proper use of the term.

>>>2. The module's "helper functions" -- which are usually called factory
>>>functions/methods because they are essentially alternative constructors
>>>of ISets -- would perhaps better be defined as classmethods of ISet;
>>>that's a common way to define instance factories in python. Except for
>>>'eq' and 'ne', the rest define an ISet of a single Interval, so they
>>>would rather be classmethods of Interval. Also the function names could
>>>take some improvement; at the very least they should not be 2-letter
>>>abbreviations.
>>
>>First, as far as having the factory functions create Interval instances
>>(Range instances in your examples), I was hoping to avoid Intervals
>>being publically "exposed."  I think it's cleaner if the end-programmer
>>only has to deal with one object interface.
> 
> First off, the python convention for names you intend to be 'private'
> is to prefix them with a single underscore, i.e. _Interval, so it was
> not obvious at all by reading the documentation that this was your
> intention. Assuming that Interval is to be exposed, I  found
> Interval.lowerThan(5) a bit more intuitive than
> IntervalSet.lowerThan(5). The only slight problem is the 'ne'/
> allExcept factory which doesn't return a continuous interval and
> therefore cannot be a classmethod in Interval.

If the factories resided in separate classes, it seems like they might 
be less convenient to use.  I wanted these things to be easily 
constructed.  Maybe a good compromise is to implement lessThan and 
greaterThan in both Interval and IntervalSet.

> On whether Interval should be exposed or not: I believe that interval
> is a useful abstraction by itself and has the important property of
> being continuous, which IntervalSet doesn't. 

Perhaps I should add a boolean function for IntervalSet called 
continuous (isContinuous?).

Having a simple
> single-class interface is a valid argument, but it may turn out to be
> restricted later. For example, I was thinking that a useful method of
> IntervalSet would be an iterator over its Intervals:
>     for interval in myIntervalSet:
>         print interval.min, interval.max

I like the idea of allowing iteration over the Intervals.

> 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.

>>I like the idea of lengthening the factory function names, but I'm not
>>sure that the factory methods would be better as class methods.
> 
> One of the main reason for introducing classmethods was to allow
> alternate constructors that play well with subclasses. So if Interval
> is subclassed, say for a FrozenInterval class,
> FrozenInterval.lowerThan() returns FrozenInterval instances
> automatically.

You've convinced me :).  I sure hate to require the programmer to have 
to type the class name when using a factory method, but I'd hate 
providing a duo of frozen and non-frozen factories even more.

>>I like the function names, but in my dialect, lessThan would be more proper.
> 
> Either (lowerThan,greaterThan) or (lessThan,moreThan) are fine with me;
> I'm very slightly in favor of the second for brevity.

Less than/greater than seem to be the usual way to pronounce < and >. 
At least it matches the Python, which uses __lt__, __le__, __gt__, and 
__ge__.  I'll stick with lessThan and greaterThan.

Thanks for your input.  I'm going to start implementing your 
suggestions.  I hope more people add feedback so I can make this an even 
better module.



More information about the Python-list mailing list