diff --git a/Param/Base/RealParameter.cpp b/Param/Base/RealParameter.cpp
index 42442005c451adb2095f6b77dd8ee58d0e851630..f1520ebf8f684a877a53f2e9ac19368bf6ae8d4d 100644
--- a/Param/Base/RealParameter.cpp
+++ b/Param/Base/RealParameter.cpp
@@ -101,11 +101,3 @@ std::string RealParameter::unit() const
 {
     return m_unit.getName();
 }
-
-std::string RealParameter::asPythonArgumentList(const std::vector<RealParameter*>& parameters)
-{
-    std::vector<std::string> args;
-    for (const auto* par : parameters)
-        args.push_back(pyfmt::printValue(par->value(), par->unit()));
-    return StringUtils::join(args, ", ");
-}
diff --git a/Param/Base/RealParameter.h b/Param/Base/RealParameter.h
index 3718d40bfab00b7757cfad30a7cdaa5f913e3cb8..bb6475d89cd43864d471bb6853bb22ebe446b66d 100644
--- a/Param/Base/RealParameter.h
+++ b/Param/Base/RealParameter.h
@@ -50,10 +50,6 @@ public:
     RealParameter& setUnit(const std::string& name);
     std::string unit() const;
 
-#ifndef SWIG
-    static std::string asPythonArgumentList(const std::vector<RealParameter*>& parameters);
-#endif
-
 protected:
     RealLimits m_limits;
     Attributes m_attr;
diff --git a/Sample/Scattering/IFormFactor.cpp b/Sample/Scattering/IFormFactor.cpp
index 58a2b3140b4fefbd6d340d0f26e4180882b2d1f1..565c377662caae91f21cb46755799a4e899ea40e 100644
--- a/Sample/Scattering/IFormFactor.cpp
+++ b/Sample/Scattering/IFormFactor.cpp
@@ -13,6 +13,7 @@
 //  ************************************************************************************************
 
 #include "Sample/Scattering/IFormFactor.h"
+#include "Base/Py/PyFmt.h"
 #include "Base/Utils/StringUtils.h"
 #include "Param/Base/RealParameter.h"
 #include "Sample/Material/WavevectorInfo.h"
@@ -53,7 +54,7 @@ bool shapeOutsideLimits(const IFormFactor& formfactor, ZLimits limits, const IRo
 } // namespace
 
 IFormFactor::IFormFactor(const NodeMeta& meta, const std::vector<double>& PValues)
-    : ISampleNode(meta, PValues)
+    : ISampleNode(meta, PValues), m_nodeMeta(meta)
 {
 }
 
@@ -83,8 +84,17 @@ std::string IFormFactor::pythonConstructor() const
     // Some formfactor names (returned by getName()) are named in a different way than others: They
     // are prepended by "FormFactor", the others aren't.
 
-    return (StringUtils::startsWith(getName(), "FormFactor") ? "" : "FormFactor") + getName() + "("
-           + RealParameter::asPythonArgumentList(m_params) + ")";
+    const std::string ctorName =
+        (StringUtils::startsWith(m_nodeMeta.className, "FormFactor") ? "" : "FormFactor")
+        + m_nodeMeta.className;
+
+
+    std::vector<std::pair<double, std::string>> arguments;
+
+    for (size_t i = 0; i < m_nodeMeta.paraMeta.size(); i++)
+        arguments.push_back({m_P[i], m_nodeMeta.paraMeta[i].unit});
+
+    return pyfmt::printFunction(ctorName, arguments);
 }
 
 double IFormFactor::volume() const
diff --git a/Sample/Scattering/IFormFactor.h b/Sample/Scattering/IFormFactor.h
index 3b5c4913fa7b8625912c019a9a7b950447d7700c..272412db6ec13bae1e64720b0acebd3f32e76b60 100644
--- a/Sample/Scattering/IFormFactor.h
+++ b/Sample/Scattering/IFormFactor.h
@@ -89,6 +89,9 @@ protected:
 
     static IFormFactor* createTransformedFormFactor(const IFormFactor& formfactor,
                                                     const IRotation& rot, kvector_t translation);
+
+protected:
+    NodeMeta m_nodeMeta; //!< stored for python code generation
 };
 
 #endif // BORNAGAIN_SAMPLE_SCATTERING_IFORMFACTOR_H