You should not stop after figuring out where the bottlenecks are, you should go on to identify them. For example, do you invoke the get_xxxx_moves() every time around?
On the chance that you do:
Instead of listing all moves each time, you may be able to reduce the work needed by
only updating the piece move lists that are affected by a move. The other ...
I need to get two things out of the way:
If your are concerned about performance, Python is not for you. The language just isn't built for this kind of thing. That said, I do think it can be useful for learning/building your first engine, but it's unlikely your engine will be very strong.
Speed improvements for an engine come from optimizations to the ...