[Python-Dev] Symmetry arguments for API expansion

Steven D'Aprano steve at pearwood.info
Tue Mar 13 07:53:07 EDT 2018


On Mon, Mar 12, 2018 at 09:49:27AM -0700, Raymond Hettinger wrote:

> * We already have a simple, traditional, portable, and readable way to 
> make the test: int(x) == x


Alas, the simple way is not always the correct way:

py> x = float('inf')
py> x == int(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: cannot convert float infinity to integer

So to be correct, you need to catch OverflowError, ValueError (in case 
of NANs), and TypeError (in case of complex numbers).

Or guard against them with isinstance() and math.isfinite() tests. But 
doing so has its own problems:

py> x = Decimal('snan')
py> math.isfinite(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: cannot convert signaling NaN to float


> * In the context of ints, the test x.is_integer() always returns True.  
> This isn't very useful.

It is if you don't know what type x is ahead of time.

    if x.is_integer():

versus:

    if isinstance(x, int) or isinstance(x, float) and x.is_integer()


> Does it cost us anything?
> * Yes, adding a method to the numeric tower makes it a requirement for 
> every class that ever has or ever will register or inherit from the 
> tower ABCs.

Could the numeric tower offer a default implementation that should work 
for most numeric types? The default could possibly even be 

    int(self) == self

Then you only have to implement your own if you have special cases to 
consider, like floats, or can optimise the test. Many numbers ought to 
know if they are integer valued, without bothering to do a full 
conversion to int. For example, Fractions could return 

    self.denominator == 1

as a cheap test for integerness.


> * Adding methods to a core object such as int() increases the 
> cognitive load for everyday users who look at dir(), call help(), or 
> read the main docs.

This is a good point, but not an overwhelming one.


> What does "API Parsimony" mean?
> * Avoidance of feature creep.
> * Preference for only one obvious way to do things.
> * Practicality (not craving things you don't really need) beats purity (symmetry and foolish consistency).
> * YAGNI suggests holding off in the absence of clear need.
> * Recognition that smaller APIs are generally better for users.

A very nice list! Thank you for that!

But the last one is true only to a point. It is possible to be too 
small. (The Python 1.5 API is *much* smaller than Python 3.6. I don't 
think that it was better.) And consider that a *consistent* API is often 
more important than a *minimalist* API.



-- 
Steve


More information about the Python-Dev mailing list