Numeric double integration
If you want to use numpy, use numpy properly. Inestead of 

for x in inner_values:
    s += func(x, y) * dA


use the more idiomatic, and much faster

s += dA * np.sum(func(inner_values, y))


Note: this requires rewriting f as 

return np.sqrt(np.maximum(0, 4 - y**2 - x**2))


so it can accept an array as an input. This does not reduce accuracy, but brings time down to a much more accaptable .04 seconds for a 100x improvement. The takeaway here is Numpy is not magic. It provides quick vectorization.