>>10
While there is a speed penalty to be allowed to do that, I don't see why this is that huge of a penalty, it just means that you can't make direct calls.
In assembly, that would be:
call rel_offset ; direct call
call [&rel_offset] ; indirect call
pointer_table:
rel_offset dd add
mov [&rel_offset], new_add
call [&rel_offset] ; calls new_add
The speed penalty for that isn't huge. It's actually very common to do this. API calls are usually done like this, the OS writes the API imports to a table (in windows, it's called the IAT, altough it doesn't have to be contigious), and they're called directly. People can even make these API calls go through many hoops, and it still doesn't affect performance much.
Common Lisp being a dynamic language does this for the majority of functions, unless you crank up the optimization settings to do direct calls, and implementations are still pretty damn fast.
SEPPLES does this too with the object vtable, and it's much worse there, you usually have to go through double indirection and the address can't even be cached and the call is done through a register instead of a known beforehand offset, and it's still not THAT slow.
I don't know much Python, but I think the problem lies in how objects are built.
Some languages, like Javascript store objects are dictionaries/hashtables by default. Doing something like that is a lot more costly than just one indirect offset. If Python is like that, I can imagine why it would be slow.