1

我正在使用 Iron Python 作为添加的“免费”工具来测试将通信包装到某些自定义硬件的 API,以便非开发团队可以通过 python 使用硬件。

但是我不知道如何让 .NETvoid func(params object[] args)映射到 Python def (*args)

这里有一些代码来解释。

我有一种允许注入日志回调以格式化和处理消息的类型,它遵循 Console.WriteLine 和 Debug.WriteLine 的签名。

public class Engine
{
    Action<string, object[]> _logger;
    public void Run()
    {
        Log("Hello '{0}'", "world");
    }
    public void SetLog(Action<string, object[]> logger)
    {
        _logger = logger;
    }
    void Log(string msg, params object[] args)
    {
        _logger(msg, args);
    }
}

在我的 IronPython 代码中

import clr
from System import *
from System.IO import Path
clr.AddReferenceToFileAndPath(Path.GetFullPath(r"MyAssembly.dll"))
from MyNamespace import *

def logger(msg, *args):
    print( String.Format(msg, args))
    print( String.Format(msg, list(args)))
    print( String.Format(msg, [args]))
    a=[]
    for i in args:
        a.append(i)
    print( String.Format(msg, a) )

e = Engine()
e.SetLog(logger)
e.Run()

输出

Hello '('world',)'
Hello 'IronPython.Runtime.List'
Hello 'IronPython.Runtime.List'
Hello 'IronPython.Runtime.List'

我想

Hello 'world'
4

2 回答 2

2

因为String.Format将您的铁 python 对象(第一个输出案例的元组,最后三个的列表)作为单个对象处理,并且不知道您希望在params object[]获得意外输出时使用 python 集合。def logger调用时会隐式创建单个 python 对象/元组。

根据您的实际用例/风格,您可以用不同的方式解决这个问题。

像 Jeff 在他的回答中解释的那样,最 Python 的方式是在他们的调用站点上扩展参数:

def logger(msg, *args):
    print( String.Format(msg, *args) )

如果您logger仅从 CLR 调用作为实现,则Action<string, object[]>您可能只有args一个类型的(非变量)参数,object[]例如

def logger(msg, args):
    print( String.Format(msg, args) )

如果您也想logger使用可变参数从 python 调用(并且您不介意来回转换),您可以这样做

def logger(msg, *args):
    print( String.Format(msg, Array[object](args)) )
于 2012-08-19T12:26:40.830 回答
2

除非我误解了你的问题,否则这应该有效:

def logger(msg, *args):
    print(String.Format(msg, *args))
于 2012-08-21T15:44:56.457 回答