如何用Boost Python遍历Python3+字典或转换为列表?
嘿,这个问题我之前升级项目的时候也踩过坑!Python 3把dict.items()的返回值从列表改成了dict_items视图对象,它是惰性迭代的,不能直接赋值给Boost Python的list对象,所以才会报那个类型错误。不过有两种简单的解决办法,看你习惯哪种:
方法1:直接遍历dict_items视图(推荐)
既然dict_items本身是可迭代的,咱们不用费劲转成列表,直接用Boost Python的迭代机制遍历就行,代码更简洁高效:
#include <boost/python.hpp> namespace bp = boost::python; // 假设myDict是你拿到的Python字典对象 bp::object items = myDict.attr("items")(); // 用C++11及以上的范围for循环直接遍历 for (bp::object pair : items) { std::string memberKey = bp::extract<std::string>(pair[0]); bp::object member = pair[1]; // 在这里处理你的键值对逻辑 // 比如打印键值:std::cout << memberKey << ": " << bp::extract<std::string>(member) << std::endl; }
如果你的项目还在用C++11之前的标准,那可以用迭代器手动遍历:
bp::object items = myDict.attr("items")(); bp::object iter = items.attr("__iter__")(); while (true) { bp::object pair; try { // Python 3里迭代器的next方法是__next__,Python 2是next pair = iter.attr("__next__")(); } catch (const bp::error_already_set&) { // 捕获StopIteration异常,清理后退出循环 PyErr_Clear(); break; } std::string memberKey = bp::extract<std::string>(pair[0]); bp::object member = pair[1]; // 处理逻辑 }
方法2:把dict_items转成列表(兼容老代码)
如果你想尽量保留原来Python 2时代的代码结构,那可以调用Python内置的list()函数把dict_items转换成列表:
bp::object list_obj = bp::import("__main__").attr("list"); bp::list myList = list_obj(myDict.attr("items")()); // 接下来就可以像Python 2那样遍历了 for (int i = 0; i < len(myList); ++i) { bp::tuple pair = bp::extract<bp::tuple>(myList[i]); std::string memberKey = bp::extract<std::string>(pair[0]); bp::object member = pair[1]; // 原来的处理逻辑不用怎么改 }
这里的关键是不能直接把myDict.attr("items")()赋值给bp::list,必须通过Python的list()构造函数来转换,因为Boost Python的list类不直接支持从dict_items对象初始化。
内容的提问来源于stack exchange,提问作者Sturm
相关产品推荐
相关产品推荐

