diff --git a/include/aidge/utils/Attributes.hpp b/include/aidge/utils/Attributes.hpp
index d3444000191022b575adaf1430319479daa5d4fc..927686cfd5cca910c5ffb25364ae4bc971ad18bf 100644
--- a/include/aidge/utils/Attributes.hpp
+++ b/include/aidge/utils/Attributes.hpp
@@ -69,6 +69,11 @@ public:
     *  be agnostic from its return type.
     */
     virtual py::object getAttrPy(const std::string& name) const = 0;
+    /* Bindable set function, does not recquire any templating.
+    *  This is thanks to py::object which allow the function to
+    *  be agnostic from ``value`` type.
+    */
+    virtual void setAttrPy(const std::string& name, py::object&& value) = 0;
 #endif
     virtual ~Attributes() {}
 };
diff --git a/include/aidge/utils/DynamicAttributes.hpp b/include/aidge/utils/DynamicAttributes.hpp
index 2af8f47e9420f266cc6eca21f167944c761db7ea..44c3b1f5e8df833344fa9b7fe72bdb4ef1e0ec12 100644
--- a/include/aidge/utils/DynamicAttributes.hpp
+++ b/include/aidge/utils/DynamicAttributes.hpp
@@ -135,7 +135,7 @@ public:
         assert(res.second && "attribute already exists");
     }
 
-    void setAttrPy(const std::string& name, py::object&& value)
+    void setAttrPy(const std::string& name, py::object&& value) override final
     {
         auto resPy = mAttrsPy.emplace(std::make_pair(name, value));
         if (!resPy.second)
@@ -204,7 +204,7 @@ private:
     // Stores C++ attributes (copy) and Python-only attributes
     // Code should be compiled with -fvisibility=hidden
     // See https://pybind11.readthedocs.io/en/stable/faq.html:
-    // “‘SomeClass’ declared with greater visibility than the type of its 
+    // “‘SomeClass’ declared with greater visibility than the type of its
     // field ‘SomeClass::member’ [-Wattributes]”
     // This map will only be populated if Python interpreter is running
     std::map<std::string, py::object> mAttrsPy;
diff --git a/include/aidge/utils/StaticAttributes.hpp b/include/aidge/utils/StaticAttributes.hpp
index a90a08b01915c461bc8951c08ee2dbd979b957de..fa450769f2fb0958f03a12623f1e9455ed60797f 100644
--- a/include/aidge/utils/StaticAttributes.hpp
+++ b/include/aidge/utils/StaticAttributes.hpp
@@ -212,7 +212,22 @@ public:
         }
 
         AIDGE_THROW_OR_ABORT(py::value_error, "attribute \"%s\" not found", name.c_str());
-    };
+    }
+
+
+    void setAttrPy(const std::string& name, py::object&& value) override final{
+        for (std::size_t i = 0; i < size(EnumStrings<ATTRS_ENUM>::data); ++i) {
+            if (name == EnumStrings<ATTRS_ENUM>::data[i]) {
+                // Cannot update attribute using reference has it would require templating
+                // Use a dirty
+                auto tmpAttr = py::cast(mAttrs);
+                py::detail::accessor_policies::tuple_item::set(tmpAttr, static_cast<py::size_t>(i), value);
+                mAttrs = py::cast<std::tuple<T...>>(tmpAttr);
+                return;
+            }
+        }
+        AIDGE_THROW_OR_ABORT(py::value_error, "attribute \"%s\" not found", name.c_str());
+    }
     #endif
 
 private:
diff --git a/python_binding/utils/pybind_Parameter.cpp b/python_binding/utils/pybind_Parameter.cpp
index 2957876f31ad0781a36905cef3a5ae88934b6a8a..056cbf16b491a40c40dee16d2ed891c4974a53dc 100644
--- a/python_binding/utils/pybind_Parameter.cpp
+++ b/python_binding/utils/pybind_Parameter.cpp
@@ -21,7 +21,8 @@ void init_Attributes(py::module& m){
     .def("has_attr", &Attributes::hasAttr, py::arg("name"))
     .def("get_attr_type", &Attributes::getAttrType, py::arg("name"))
     .def("get_attrs_name", &Attributes::getAttrsName)
-    .def("get_attr", &Attributes::getAttrPy, py::arg("name"));
+    .def("get_attr", &Attributes::getAttrPy, py::arg("name"))
+    .def("set_attr", &Attributes::setAttrPy, py::arg("name"), py::arg("value"));
 
     py::class_<DynamicAttributes, std::shared_ptr<DynamicAttributes>, Attributes>(m, "DynamicAttributes")
     .def("add_attr", &DynamicAttributes::addAttrPy, py::arg("name"), py::arg("value"))