请考虑以下事项:
PyObject* fmt = PyUnicode_FromString("{0!r}");
PyObject* tup = PyTuple_New(2);
PyTuple_SetItem(tup, 0, PyUnicode_FromString("hello"));
PyTuple_SetItem(tup, 1, PyUnicode_FromString("world"));
PyObject* formatted = PyObject_CallMethod(fmt, "format", "O", tup);
PyObject* bytes = PyUnicode_AsEncodedString(formatted, "UTF-8", "strict");
printf(PyBytes_AS_STRING(bytes));
我希望它像这个python代码一样:
>>> u'{0!r}'.format((u"hello", u"world"))
"(u'hello', u'world')"
然而我的输出只是:
u'hello'
我可以想象它实际上是在调用函数:
>>> u'{0!r}'.format(u"hello", u"world")
u'hello'
我在寻找:
答案 0 :(得分:1)
问题似乎与Py_BuildValue
的工作方式有关(似乎PyObject_CallMethod
使用了这种方式)。来自docs(强调我的):
Py_BuildValue()并不总是构建一个元组。它只构建一个元组 如果其格式字符串包含两个或更多格式单位。如果是格式 string为空,返回None; 如果它只包含一种格式 单位,它返回该格式单位描述的任何对象。 To 强制它返回大小为0或1的元组,将格式括起来 字符串。
这意味着,不是将格式字符串"O"
与tup
一起构建到args=(tup,)
并调用fmt.format(*args)
(扩展为fmt.format(("hello", "world"))
,而是构建{{1} }},所以args=tup
扩展为fmt.format(*args)
,正如您所想。解决方案也在docs:
要强制它返回大小为0或1的元组,请将格式括起来 字符串。
所以,只需改变:
fmt.format("hello", "world")
要:
PyObject* formatted = PyObject_CallMethod(fmt, "format", "O", tup);
您获得了PyObject* formatted = PyObject_CallMethod(fmt, "format", "(O)", tup);
的所需输出。完整代码段(使用('hello', 'world')
编译):
gcc thissnippet.c -I /usr/include/python3.4m/ -l python3.4m