1

I want to do something every time I add two integers in my TestClass.

import builtins

class myInt(int):
    def __add__(self, other):
        print("Do something")

class TestClass:
    def __init__(self):
        builtins.int = myInt

    def testMethod(self):
        a = 1
        b = 2
        c = a + b

When I call my testMethod nothing happens, however if I define it like this I get the desired effect:

    def testMethod(self):
        a = int(1)
        b = 2
        c = a + b

Is it possible to make this work for all int literals without having to typecast them before the operations?

2

1 Answer 1

3

Sorry, it's not possible without building your own custom interpreter. Literal objects aren't constructed by calling the constructor in __builtins__, they are constructed using opcodes that directly call the builtin types.

Also immutable literals are constructed when the code is compiled, so you were too late anyway. If you disassemble testMethod you'll see it simply uses the constants that were compiled, it doesn't attempt to construct them:

>>> dis.dis(TestClass.testMethod)
  5           0 LOAD_CONST               1 (1)
              2 STORE_FAST               1 (a)

  6           4 LOAD_CONST               2 (2)
              6 STORE_FAST               2 (b)

  7           8 LOAD_FAST                1 (a)
             10 LOAD_FAST                2 (b)
             12 BINARY_ADD
             14 STORE_FAST               3 (c)
             16 LOAD_CONST               0 (None)
             18 RETURN_VALUE

Mutable literals are constructed at runtime but they use opcodes to construct the appropriate value rather than calling the type:

>>> dis.dis(lambda: {'a': 1, 'b': 2})
  1           0 LOAD_CONST               1 (1)
              2 LOAD_CONST               2 (2)
              4 LOAD_CONST               3 (('a', 'b'))
              6 BUILD_CONST_KEY_MAP      2
              8 RETURN_VALUE

You could do something along the lines of what you want by parsing the source code (use builtin compile() with ast.PyCF_ONLY_AST flag) then walking the parse tree and replacing int literals with a call to your own type (use ast.NodeTransformer). Then all you have to do is finish the compilation (use compile() again). You could even do that with an import hook so it happens automatically when your module is imported, but it will be messy.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.