Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Polymorphism and calls from a module

I'm having trouble with the use of polymorphism in object oriented programming in python. Here I define a specialisation of the list class that overrides the append and setitem methods

class MyList(list):
    def __setitem__(self, key,value):
        super(MyList,self).__setitem__(key,value)
        print("bubu")
    def append(self,value):
        super(MyList,self).append(value)
        print("bibi")

Now if I test this class with

myobj = MyList()
myobj.append(1) 
myobj[0]=3

I get "bibi", and then "bubu", as expected. But if I use a MyList object with an external module

import heapq
myobj = MyList()
heapq.heappush(myobj,1) 

The function heappush from heapq is supposed to call myobj.append (I checked the sources https://github.com/python/cpython/blob/3.10/Lib/heapq.py). But I get no "bibi" this time ! Isn't the "append" called supposed to be that of the instance passed in arguments ?

Where are my bibis ?? :)

like image 562
jdambrine Avatar asked Jan 20 '26 17:01

jdambrine


1 Answers

If you run Python without any arguments and enter the following, I am fairly certain you will get no import error:

>>>
>>>
>>> from _heapq import *
>>>

I mention this because if you just look a little more deeply into the source code for heapq, you will see at the bottom:

# If available, use C implementation
try:
    from _heapq import *
except ImportError:
    pass
... # etc.

And since we had no reason to believe your MyList implementation of method append was not working correctly, that alone should have suggested that the heapq.heappush method was not calling the append method on the list. And now we no why.

Update

To load heapq without _heapq:

import sys
import importlib
import _heapq

 # Make _heapq unloadable
del _heapq
sys.modules['_heapq'] = None

# heapq was already loaded with _heapq; get a reference:
heapq = sys.modules['heapq']
# reload heapq, but this time without _heapq:
importlib.reload(heapq)

class MyList(list):
    def __setitem__(self, key,value):
        super(MyList,self).__setitem__(key,value)
        print("bubu")
    def append(self,value):
        super(MyList,self).append(value)
        print("bibi")

myobj = MyList()
heapq.heappush(myobj,1)

Prints:

bibi
bubu

Interesting that 'bubu' and 'bibi' print. This is the result of _siftdown method that heappush finally calls that results in 'bubu'.

like image 187
Booboo Avatar answered Jan 22 '26 07:01

Booboo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!