it is not feasable to do numerical work in python itself, in reality python acts as a construction kit dsl for allocating and manipulating foreign (c and fortran) structures. this is usually sufficient as one can see by the massive success of libraries like numpy. when you are writing novel numeric code though, you have to figure out how to match it to the numpy's model. this is also not usually a problem, since matching it to numpy's model usually makes it architecturally performant. but one is still wearing a kind of straight jacket at the end of the day.
when i was doing computation chemistry, i wrote a lot of code from scratch in fortran and lisp, and it was entirely feasable to do mainloops purely in lisp, implementing algorithms close to their paper versions.
there are all kinds of aspects of lisp that make it pleasant to work with in computational science area, but this is already a tldr. i'll mention one, it's possible to rig your code in a way that a long running batch process will not lose its state without much code overhead. since lisp lets you recover from error without unwinding the stack, you can trust that after hours or days of computation an error is not going to cost you full progress loss. often times you can redefine the offending part of code, and continue processing.
From the point of view of code generation, its JIT takes advantage of being built on top of LLVM's optimisations.
* Julia has multiple dispatch like in CLOS, except generic functions can devirtualize their arguments, and can be inlined, making the composition of many small function calls significantly faster.
* All functions (except a dozen or so internal builtins) are generic functions which can have methods added to them, and all objects can be dispatched on.
* Objects can be isbits and allocated inline in an array or stack allocated without any pointer indirection.
* Julia's type system is parametric, and things like Array is parameterized on it's contents, meaning that you can dispatch on thing like Array{Int} as a distinct type from Array{Quaternion{Float64}}.
There's lots of things Common Lisp does really well, but I really do think in the niche of numerical computing, Julia just blows it out of the water for performance and also ecosystem size / vibrancy.
* Lisp compilers make stupid fast self contained executables but the language is still dynamically typed
* C FFI story is mature and works great but you actually have full garbage collection still, no GIL, no reference counting.
* Did I mention no GIL? Full OS threads available for multithreaded workloads.