Repository: qutip/qutip (python)

Issue:
Instantiating a qt.QobjEvo with a qt.coefficient
It is possible to instantiate a qt.QobjEvo object with a qt.coefficient. However, the "args" argument QobjEvo does not behave as expected. Is this a bug, or is it incorrect to pass a qt.coefficient object to qt.QobjEvo? I am using qutip v5.0.4

```
import qutip as qt
A = qt.sigmaz()
def f(t, args):
    return t + args["g"]

coeff = qt.coefficient(f, args={"g":1})

evo_1 = qt.QobjEvo([A, coeff])
evo_2 = qt.QobjEvo([A, coeff], args={"g:2}) # Updating the args dictionary does nothing.

assert evo_1(1) == evo_2(1) 
```

Pull request:
Fix bug were args are not properly updated at coefficient creation.
**Description**
Fix bug were args are not properly updated at coefficient creation when initialised from another coefficient.
fix #2646

Patch:
diff --git a/doc/changes/2646.bugfix b/doc/changes/2646.bugfix
new file mode 100644
index 000000000..fa2baff1f
--- /dev/null
+++ b/doc/changes/2646.bugfix
@@ -0,0 +1,2 @@
+Fix coefficient `args` not being properly updated
+when initiated from another coefficient.
diff --git a/qutip/core/coefficient.py b/qutip/core/coefficient.py
index 3d5698de1..14315d49c 100644
--- a/qutip/core/coefficient.py
+++ b/qutip/core/coefficient.py
@@ -40,7 +40,9 @@ class StringParsingWarning(Warning):
     pass
 
 
-def _return(base, **kwargs):
+def _return(base, args=None, **kwargs):
+    if args is not None:
+        base = base.replace_arguments(args)
     return base
 
 
@@ -61,8 +63,8 @@ def coefficient(
     base: CoefficientLike,
     *,
     tlist: ArrayLike = None,
-    args: dict = {},
-    args_ctypes: dict = {},
+    args: dict = None,
+    args_ctypes: dict = None,
     order: int = 3,
     compile_opt: dict = None,
     function_style: str = None,
@@ -177,8 +179,8 @@ def coefficient(
     """
     kwargs.update({
         "tlist": tlist,
-        'args': args,
-        'args_ctypes': args_ctypes,
+        'args': args or {},
+        'args_ctypes': args_ctypes or {},
         'order': order,
         'compile_opt': compile_opt,
         'function_style': function_style,
@@ -190,6 +192,7 @@ def coefficient(
             return coefficient_builders[type_](base, **kwargs)
 
     if callable(base):
+        args = args or {}
         op = FunctionCoefficient(base, args.copy(), style=function_style)
         if not isinstance(op(0), numbers.Number):
             raise TypeError("The coefficient function must return a number")


Test patch:
diff --git a/qutip/tests/core/test_coefficient.py b/qutip/tests/core/test_coefficient.py
index ea87c122d..b4a2e6e8c 100644
--- a/qutip/tests/core/test_coefficient.py
+++ b/qutip/tests/core/test_coefficient.py
@@ -161,6 +161,17 @@ def test_CoeffCallArguments(base, tol):
     _assert_eq_over_interval(coeff, expected, rtol=tol)
 
 
+def test_coefficient_update_args():
+
+    def f(t, a):
+        return a
+
+    coeff1 = coefficient(f, args={"a": 1})
+    coeff2 = coefficient(coeff1, args={"a": 2})
+
+    assert coeff2(0) == 2
+
+
 @pytest.mark.parametrize(['style'], [
     pytest.param("func", id="func"),
     pytest.param("array", id="array"),