【问题标题】:Boost Python 3 iterate over dictBoost Python 3迭代dict
【发布时间】:2019-07-19 14:49:55
【问题描述】:

我使用 (Python 2.7) 以这种方式迭代 dict

boost::python::list myList = myDict.items();
for(int i = 0; i < len(myList); i++)
{
     pytuple pair = extract<pytuple>(itemsView[t]);
     string memberKey = extract<string>(pair[0]);
     object member = pair[1];
}

但是在升级到 3.7 之后,items() 不再返回一个列表,而是一个 view,只有在对其进行迭代后才会实现。

如果我尝试从 items() 初始化一个列表,它会失败说 TypeError: Expecting an object of type list; got an object of type dict_items instead

如何使用 Boost Python 迭代 Python 3+ 字典?

或者, 如何将字典转换为列表?

【问题讨论】:

  • 你不能使用casting as list(dict.items())吗?
  • 那行得通。发生的事情是这个错误来自另一个地方,我尝试做类似的事情,但这次是proxy_dict。任何想法如何解决下一个问题?我现在的做法是:call_method&lt;pylist&gt;(proxyDict.ptr(), "items");
  • 假设您给出的答案,您现在设法解决了。无论如何,很乐意提供帮助:)
  • 我已经在*.com/a/67038962/4657412发布了懒惰的做法(避免转换为列表,并使用 stl 样式迭代器进行迭代)

标签: python c++ dictionary boost


【解决方案1】:

扩展欧内斯特的评论,答案是将view 转换为列表:

auto myList = list(myDict.items());

如果是代理字典,则需要执行以下操作:

auto myList = list(call_method<object>(myProxyDict.ptr(), "items"));

【讨论】:

    【解决方案2】:

    你也可以采用这种方法

    boost::python::list keys = boost::python::list(global.keys());
    for (int i = 0; i < len(keys); ++i) {
        boost::python::extract<std::string> extractor(keys[i]);
        if (extractor.check()) {
            std::string key = extractor();
    
            // access the dict via global[key] to the value
        }
    }
    

    【讨论】:

      【解决方案3】:

      另一种方式:

      
      object theIterable = theObjectDict.keys();
      object theIterator = theIterable.attr("__iter__")();
      
      do
      {
              try
              {
                  object theKey = theIterator.attr("__next__")();
                  std::string memberkey = extract< std::string >( theKey );
      
              }
              catch(...)
              {
                PyObject*theError = PyErr_Occurred();
                if( theError )
                {
                    PyObject *ptype, *pvalue, *ptraceback;
                    PyErr_Fetch(&ptype, &pvalue, &ptraceback);
                    if( ptype == PyExc_StopIteration )
                    {
                          PyErr_Clear();
                          break;
                    }
                }
                throw;
              }
      } while(1);
      
      

      【讨论】: