(original) (raw)

On 14 March 2018 at 08:29, Tim Peters <tim.peters@gmail.com> wrote:
\[Tim\]
>> An obvious way to extend it is for Fraction() to look for a special
\>> method too, say "\_as\_integer\_ratio()".

\[Greg Ewing\]
\> Why not \_\_as\_integer\_ratio\_\_?

Because. at this point, that would be beating a dead horse ;-)

I'm not so sure about that, as if we define a protocol method for it, then we'd presumably also define an "operator.as\_integer\_ratio" function, and that function could check \_\_index\_\_ in addition to checking the new protocol method.

For example:

def as\_integer\_ratio(n):
# Automatically accept true integers
if hasattr(n, "\_\_index\_\_"):
return (n.\_\_index\_\_(), 1)
# New reserved protocol method
if hasattr(n, "\_\_integer\_ratio\_\_"):
return n.\_\_integer\_ratio\_\_()
# Historical public protocol method
if hasattr(n, "as\_integer\_ratio"):
return n.as\_integer\_ratio()
# Check for lossless integer conversion
try:
int\_n = int(n)
except TypeError:
pass
else:
if int\_n == n:
return (int\_n, 1)
raise TypeError(f"{type(n)} does not support conversion to an integer ratio")

Similarly, on the "operator.is\_integer" front:

def is\_integer(n):
# Automatically accept true integers
if hasattr(n, "\_\_index\_\_"):
return True
# New reserved protocol method
if hasattr(n, "\_\_is\_integer\_\_"):
return n.\_\_is\_integer\_\_()
# Historical public protocol method
if hasattr(n, "is\_integer"):
return n.is\_integer()
# As a last resort, check for lossless int conversion
return int(n) == n

Cheers,
Nick.

P.S. I've suggested "operator" as a possible location, since that's where we put "operator.index", and it's a low level module that doesn't bring in any transitive dependencies. However, putting these protocol wrappers somewhere else (e.g. in "math" or "numbers") may also make sense.

--
Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia