# Does ForwardDiff work with Python functions?

**URL:** <https://discourse.julialang.org/t/does-forwarddiff-work-with-python-functions/57851>\
**Category:** General Usage\
**Tags:** question, forwarddiff\
**Created:** [March 24, 2021, 8:56am UTC](https://discourse.julialang.org/t/does-forwarddiff-work-with-python-functions/57851 "2021-03-24T08:56:11Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![arif](https://avatars.discourse-cdn.com/v4/letter/a/74df32/32.png) [@arif](https://discourse.julialang.org/u/arif)\
**Post date:** [March 24, 2021, 8:56am UTC](https://discourse.julialang.org/t/does-forwarddiff-work-with-python-functions/57851/1 "2021-03-24T08:56:12Z")

</div>

Hi all, trying to use `ForwardDiff` on a Python function and getting errors. Here is a MWE

```julia
using PyCall
np = pyimport("numpy")

function npsin(x)
    np.sin(x)
end

function dnpsin(x)
    ForwardDiff.derivative(npsin, x)
end

```

`dnpsin(π/2)` gives following error

```julia
MethodError: no method matching Float64(::ForwardDiff.Dual{ForwardDiff.Tag{typeof(npsin),Float64},Float64,1})
Closest candidates are:
  Float64(::Real, ::RoundingMode) where T<:AbstractFloat at rounding.jl:200
  Float64(::T) where T<:Number at boot.jl:716
  Float64(::Irrational{:mad_constant}) at irrationals.jl:189
  ...

Stacktrace:
 [1] convert(::Type{Float64}, ::ForwardDiff.Dual{ForwardDiff.Tag{typeof(npsin),Float64},Float64,1}) at ./number.jl:7
 [2] cconvert(::Type{T} where T, ::ForwardDiff.Dual{ForwardDiff.Tag{typeof(npsin),Float64},Float64,1}) at ./essentials.jl:388
 [3] macro expansion at /home/arif/.julia/packages/PyCall/tqyST/src/exception.jl:95 [inlined]
 [4] PyObject(::ForwardDiff.Dual{ForwardDiff.Tag{typeof(npsin),Float64},Float64,1}) at /home/arif/.julia/packages/PyCall/tqyST/src/conversions.jl:23
 [5] _pycall!(::PyObject, ::PyObject, ::Tuple{ForwardDiff.Dual{ForwardDiff.Tag{typeof(npsin),Float64},Float64,1}}, ::Int64, ::Ptr{Nothing}) at /home/arif/.julia/packages/PyCall/tqyST/src/pyfncall.jl:24
 [6] _pycall! at /home/arif/.julia/packages/PyCall/tqyST/src/pyfncall.jl:11 [inlined]
 [7] #_#116 at /home/arif/.julia/packages/PyCall/tqyST/src/pyfncall.jl:86 [inlined]
 [8] (::PyObject)(::ForwardDiff.Dual{ForwardDiff.Tag{typeof(npsin),Float64},Float64,1}) at /home/arif/.julia/packages/PyCall/tqyST/src/pyfncall.jl:86
 [9] npsin(::ForwardDiff.Dual{ForwardDiff.Tag{typeof(npsin),Float64},Float64,1}) at ./In[181]:2
 [10] derivative at /home/arif/.julia/packages/ForwardDiff/sqhTO/src/derivative.jl:14 [inlined]
 [11] dnpsin(::Float64) at ./In[185]:2
 [12] top-level scope at In[187]:1
 [13] include_string(::Function, ::Module, ::String, ::String) at ./loading.jl:1091

```

---

<div class="post-metadata">

**Author:** ![jacobusmmsmit](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jacobusmmsmit/32/217669_2.png) [@jacobusmmsmit](https://discourse.julialang.org/u/jacobusmmsmit)\
**Post date:** [March 24, 2021, 10:29am UTC](https://discourse.julialang.org/t/does-forwarddiff-work-with-python-functions/57851/2 "2021-03-24T10:29:27Z")

</div>

From the [ForwardDiff docs limitations page](https://juliadiff.org/ForwardDiff.jl/stable/user/limitations/):

> [@](#):
>
> **The target function can only be composed of generic Julia functions.**

This is due to the way ForwardDiff works by passing a dual number to the function in order to propagate and store derivative information. This won’t be possible for Python functions as they don’t know how to handle being passed a dual number.

Specifically, what I think is happening in the MWE is Julia wants to call the Python function with its arguments (which in this case is a `Dual`) and so it wants the inputs to be Floats. It calls `Float` on the input `Dual` so Python can use `np.sin` and then Julia realises that you can’t convert a `Dual` to a `Float` and spits out the error.
