Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

How to pass *varargs?#1772

Answeredbyfilmor
henon asked this question inQ&A
Apr 24, 2022· 3 comments· 5 replies
Discussion options

How do you pass a variable list of arguments in pythonnet? The problem is the functionnumpy.gradient(f, *varargs, axis=None, edge_order=1) as documented here:https://numpy.org/doc/stable/reference/generated/numpy.gradient.html

Here is an example in python

>>>importnumpyasnp>>>dx=4.0>>>dy=5.0>>>zX=[[1,2,3],[4,5,6],[8,9,0]]>>>np.gradient(zX,dx,dy)[array([[0.75 ,0.75 ,0.75 ],       [0.875,0.875,-0.375],       [1.   ,1.   ,-1.5  ]]),array([[0.2,0.2,0.2],       [0.2,0.2,0.2],       [0.2,-0.8,-1.8]])]>>>

I tried to pass the variable args with the args tuple but then the python function complains that the number of arguments is incorrect.

Python.Runtime.PythonException: TypeError : invalid number of arguments ['  File "C:\\Users\\henon\\AppData\\Local\\python-3.7.3-embed-amd64\\lib\\numpy\\lib\\function_base.py", line 1013, in gradient\n    raise TypeError("invalid number of arguments")\n']   at Python.Runtime.PyObject.Invoke(PyTuple args, PyDict kw)   at Python.Runtime.PyObject.InvokeMethod(String name, PyTuple args, PyDict kw)

I also tried to pass it as kw["varargs"] but then python says there is no kwarg named "varargs"

So how to call that function?

You must be logged in to vote

You can see the available overloads here:

/// <summary>
/// InvokeMethod Method
/// </summary>
/// <remarks>
/// Invoke the named method of the object with the given arguments.
/// A PythonException is raised if the invocation is unsuccessful.
/// </remarks>
publicPyObjectInvokeMethod(stringname,paramsPyObject[]args)
{
if(name==null)thrownewArgumentNullException(nameof(name));
if(args==null)thrownewArgumentNullException(nameof(args));
if(args.Contains(null))thrownewArgumentNullException();
PyObjectmethod=GetAttr(name);

Replies: 3 comments 5 replies

Comment options

I have an update, looks like I can pass a second tuple after the args tuple and then I am getting a different error so this is a step in the right direction. But I am still stumped as to what the function really expects

using(Py.GIL()){dynamicnp=Py.Import("numpy");dynamiczX=np.array(new[,]{{1,2,3},{4,5,6},{8,9,0}});Console.WriteLine(zX.__repr__());varresult=(npasPyObject).InvokeMethod("gradient",newPyTuple(newPyObject[]{zXasPyObject}),newPyTuple(newPyObject[]{newPyFloat(4.0),newPyFloat(5.0),}));Console.WriteLine(result.InvokeMethod("__repr__"));}

Exception:

Python.Runtime.PythonException: ValueError : when 1d, distances must match the length of the corresponding dimension ['  File "C:\\Users\\henon\\AppData\\Local\\python-3.7.3-embed-amd64\\lib\\numpy\\lib\\function_base.py", line 1004, in gradient\n    raise ValueError("when 1d, distances must match "\n']   at Python.Runtime.PyObject.Invoke(PyObject[] args)   at Python.Runtime.PyObject.InvokeMethod(String name, PyObject[] args)

Any ideas@filmor ?

You must be logged in to vote
1 reply
@henon
Comment options

Nah, looks like the second tuple is interpreted as kwargs because I can't pass additional kw args:

varresult=(npasPyObject).InvokeMethod("gradient",newPyTuple(newPyObject[]{zXasPyObject}),newPyTuple(newPyObject[]{newPyFloat(4.0),newPyFloat(5.0),}),newPyDict(){["edge_order"]=newPyInt(1)});

This again leads to invalid arguments errorPython.Runtime.PythonException: TypeError : invalid number of arguments

Comment options

This should work according to my understanding:

InvokeMethod('gradient',newPyTuple(f,varArg1,varArg2),kwArgs)
You must be logged in to vote
1 reply
@henon
Comment options

Yeah, that was what I would have expected too but it does not. That was what I tried initially. It givesTypeError : invalid number of arguments
I am getting the feeling this is a bug.

Comment options

You can see the available overloads here:

/// <summary>
/// InvokeMethod Method
/// </summary>
/// <remarks>
/// Invoke the named method of the object with the given arguments.
/// A PythonException is raised if the invocation is unsuccessful.
/// </remarks>
publicPyObjectInvokeMethod(stringname,paramsPyObject[]args)
{
if(name==null)thrownewArgumentNullException(nameof(name));
if(args==null)thrownewArgumentNullException(nameof(args));
if(args.Contains(null))thrownewArgumentNullException();
PyObjectmethod=GetAttr(name);
PyObjectresult=method.Invoke(args);
method.Dispose();
returnresult;
}
/// <summary>
/// InvokeMethod Method
/// </summary>
/// <remarks>
/// Invoke the named method of the object with the given arguments.
/// A PythonException is raised if the invocation is unsuccessful.
/// </remarks>
publicPyObjectInvokeMethod(stringname,PyTupleargs)
{
if(name==null)thrownewArgumentNullException(nameof(name));
if(args==null)thrownewArgumentNullException(nameof(args));
PyObjectmethod=GetAttr(name);
PyObjectresult=method.Invoke(args);
method.Dispose();
returnresult;
}
/// <summary>
/// InvokeMethod Method
/// </summary>
/// <remarks>
/// Invoke the named method of the object with the given arguments.
/// A PythonException is raised if the invocation is unsuccessful.
/// </remarks>
publicPyObjectInvokeMethod(PyObjectname,paramsPyObject[]args)
{
if(name==null)thrownewArgumentNullException(nameof(name));
if(args==null)thrownewArgumentNullException(nameof(args));
if(args.Contains(null))thrownewArgumentNullException();
PyObjectmethod=GetAttr(name);
PyObjectresult=method.Invoke(args);
method.Dispose();
returnresult;
}
/// <summary>
/// InvokeMethod Method
/// </summary>
/// <remarks>
/// Invoke the named method of the object with the given arguments.
/// A PythonException is raised if the invocation is unsuccessful.
/// </remarks>
publicPyObjectInvokeMethod(PyObjectname,PyTupleargs)
{
if(name==null)thrownewArgumentNullException(nameof(name));
if(args==null)thrownewArgumentNullException(nameof(args));
PyObjectmethod=GetAttr(name);
PyObjectresult=method.Invoke(args);
method.Dispose();
returnresult;
}
/// <summary>
/// InvokeMethod Method
/// </summary>
/// <remarks>
/// Invoke the named method of the object with the given arguments
/// and keyword arguments. Keyword args are passed as a PyDict object.
/// A PythonException is raised if the invocation is unsuccessful.
/// </remarks>
publicPyObjectInvokeMethod(stringname,PyObject[]args,PyDict?kw)
{
if(name==null)thrownewArgumentNullException(nameof(name));
if(args==null)thrownewArgumentNullException(nameof(args));
if(args.Contains(null))thrownewArgumentNullException();
PyObjectmethod=GetAttr(name);
PyObjectresult=method.Invoke(args,kw);
method.Dispose();
returnresult;
}
/// <summary>
/// InvokeMethod Method
/// </summary>
/// <remarks>
/// Invoke the named method of the object with the given arguments
/// and keyword arguments. Keyword args are passed as a PyDict object.
/// A PythonException is raised if the invocation is unsuccessful.
/// </remarks>
publicPyObjectInvokeMethod(stringname,PyTupleargs,PyDict?kw)
{
if(name==null)thrownewArgumentNullException(nameof(name));
if(args==null)thrownewArgumentNullException(nameof(args));
PyObjectmethod=GetAttr(name);
PyObjectresult=method.Invoke(args,kw);
method.Dispose();
returnresult;
}

So we have

  • PyTuple
  • params PyObject[]
  • PyObject[], PyDict
  • PyTuple, PyDict

It's not ideal as it only has overloads with aPyObject name for the first two functions and the .NET varargs will probably hide the singlePyTuple overload (not sure about that).

I'm not sure why you'd think any of your attempts here should work. The variant given by@lostmsu could maybe also run into selecting the wrong overload (theparams one), I'd have to check the rules.

Does any of these work?

  • np.gradient(zX, 4.0, 5.0) (using the fact thatnp isdynamic, without additionalkwArgs)
  • np.InvokeMethod(new PyObject[] {zX, new PyFloat(4.0), new PyFloat(5.0)}, kwArgs)
You must be logged in to vote
3 replies
@henon
Comment options

Thanks for your time looking into this. Both your suggestions don't work. The dynamic version givesPython.Runtime.PythonException: TypeError : invalid number of arguments as does the second option. Do you think pythonnet is missing an overload for this kind of python function?

@henon
Comment options

I reopened this as an issue, as it is impossible to pass the *varargs.#1804

@henon
Comment options

OK, I was wrong,@filmor 's answer works with the current preview version of pythonnet, it just had a typo. The working code is:

varkwArgs=newPyDict(){["edge_order"]=newPyInt(1)};varresult=(npasPyObject).InvokeMethod("gradient",newPyObject[]{(zXasPyObject),newPyFloat(4.0),newPyFloat(5.0)},kwArgs);
Answer selected byhenon
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Category
Q&A
Labels
None yet
3 participants
@henon@filmor@lostmsu
Converted from issue

This discussion was converted from issue #1771 on April 25, 2022 08:57.


[8]ページ先頭

©2009-2025 Movatter.jp