Python: overwrite __int__

Question:

A working solution, which returns integers, was given in Overload int() in Python.

However, it works only for returning int, but not float or let’s say a list:

class Test:
    def __init__(self, mylist):
        self.mylist = mylist
    def __int__(self):
        return list(map(int, self.mylist))

t = Test([1.5, 6.1])
t.__int__()   # [1, 6]
int(t)

Thus t.__int__() works, but int(t) gives TypeError: __int__ returned non-int (type list).

Thus, is there a possibility to fully overwrite int, maybe with __getattribute__ or metaclass?

Answers:

From the doc of __int__

Called to implement the built-in functions complex(), int() and float(). Should return a value of the appropriate type.

Here your method return a list and not an int, this works when calling it explictly but not using int() which checks the type of what is returned by the __int__


Here is a working example of what if could be, even if the usage if not very pertinent

class Test:
    def __init__(self, mylist):
        self.mylist = mylist
    def __int__(self):
        return int(sum(self.mylist))
Answered By: azro

The __int__, __float__, … special methods and various others do not overwrite their respective type such as int, float, etc. These methods serve as hooks that allow the types to ask for an appropriate value. The types will still enforce that a proper type is provided.

If required, one can actually overwrite int and similar on the builtins module. This can be done anywhere, and has global effect.

import builtins

# store the original ``int`` type as a default argument
def weakint(x, base=None, _real_int=builtins.int):
    """A weakly typed ``int`` whose return type may be another type"""
    if base is None:
        try:
            return type(x).__int__(x)
        except AttributeError:
            return _real_int(x)
    return _real_int(x, base)

# overwrite the original ``int`` type with the weaker one
builtins.int = weakint

Note that replacing builtin types may violate assumptions of code about these types, e.g. that type(int(x)) is int holds true. Only do so if absolutely required.

This is an example of how to replace int(...). It will break various features of int being a type, e.g. checking inheritance, unless the replacement is a carefully crafted type. A full replacement requires emulating the initial int type, e.g. via custom subclassing checks, and will not be completely possible for some builtin operations.

Answered By: MisterMiyagi
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.