Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to support %x formatting on a class that emulates int

I haven't seen a way to do this. I am in Python 3.6.1 (v3.6.1:69c0db5050, Mar 21 2017, 01:21:04). MacOS under Sierra, though we'll need this to work on Python 2.

I have a custom class which does something which looks like an int with subfield decoding. For my own reasons, I want to be able to do things both like

inst * 4

and

inst.subfield << 1

(where subfield is an attribute of inst). These objects are highly overloaded, and e.g. printing inst will dump the subfields for viewing.

This is all done by overloading all the custom functions to handle the math and interaction with other objects. In general, it works really well, with one glaring exception: printing. For the most part, a user can forget this isn't really an integer and use it like one, but using the integer print commands won't work:

print("%#x"%inst)
TypeError: %x format: an integer is required, not CustomType

I do have __int__ overloaded, and int(inst) returns an integer as expected.

Is there any way to make this work? It's a minor annoyance, but one I'd like to fix.

Also, I do have __format__ implemented. So '{0:x}'.format(inst) works, but the print above doesn't.

Thanks!

like image 300
Corley Brigman Avatar asked Mar 05 '18 20:03

Corley Brigman


Video Answer


1 Answers

You need to implement __int__ and __index__:

class X(object):
    def __int__(self):
        return 42
    def __index__(self):
        return 42

x = X()
print('%#x' % x)

output:

0x2a

From the docs for __index__:

Called to implement operator.index(), and whenever Python needs to losslessly convert the numeric object to an integer object (such as in slicing, or in the built-in bin(), hex() and oct() functions). Presence of this method indicates that the numeric object is an integer type. Must return an integer.

So __index__ is called by hex(), as can be seen by looking at the relevant source code in PyNumber_ToBase.

like image 126
ekhumoro Avatar answered Nov 15 '22 03:11

ekhumoro