technically, apart from mhamptons comment, there are two problems: (I've just briefly looked at the code and maybe I didn't understand it)
- your code is recursive and that is not a good idea for python.
- you rip apart the expression and before each recursion and then you partially rebuild it with reduce. this creates a bunch of calculations for a new expression which you don't need if your differentiator would take a list of operands and a operation directly.