vector_indexing_suite返回的奇怪对象 [英] weird object returned by vector_indexing_suite
问题描述
我有一个
std::vector<const T*>
我从c ++函数返回的
:
that I return from a c++ function:
getallTs()
我用以下方法公开了T类:
I have exposed the T class with:
class_<T,T*>
和向量是这样的:
class_<std::vector<const T*> >("TsList")
.def(vector_indexing_suite<std::vector<const T*>,true>())
;
NoProxy参数是什么意思?
What does the NoProxy argument mean?
我这样公开函数:
def("getallTs", getallTs,
return_value_policy<return_by_value>{});
我观察到一种奇怪的行为.
I observe a weird behaviour.
当我从python调用时
When I call from python
tlist = getallTs()
我得到一个TsList对象.
I get a TsList object.
len(tlist)
有效.
tlist[<anycorrectindex>].<someattribute>
也可以.
但是,如果我只是
print(tlist[0])
和
print(tlist[100])
python打印
object T at <address>
此地址对于tlist中的所有T都是相同的.
This address is the same for all the Ts in tlist.
此外,我无法使用python for循环遍历Tlist.
Also, I cannot iterate over Tlist with a python for loop.
for t in tlist:
不起作用.
任何想法我将向量和函数暴露给python的方式有什么问题吗?
Any ideas what is wrong with the way I am exposing the vector and the function to python?
我了解每个包装c ++ T的python对象都包含一个指向T的原始指针. 这些T实例在整个过程中都存在于全局表中.
I understand the python objects that each wrap a c++ T hold a raw pointer to T. These T instances exist throughout the process in a global table.
c ++函数重新调整了指向这些实例的指针的向量. indexing_suite对这些有何作用?
The c++ function retunrns a vector of pointers to those instances. What does indexing_suite do with those?
谢谢
推荐答案
按索引访问元素时,索引套件默认提供元素的代理,以此为Python用户经常使用的可变类型提供参考语义.期望与收藏:
When accessing elements by index, the indexing suite defaults to providing a proxy to the element, as a means to provide reference semantics for mutable types that Python users will often expect with collections:
val = c[i]
c[i].m() # Mutates state, equivalent to `val.m()`
assert(val == c[i]) # Have same state.
val.m()
assert(val == c[i]) # Have same state.
在上面的示例中,val
是了解容器元素的代理对象.当NoProxy
为true
时,索引时将获得值语义,从而在每次索引访问时产生一个副本.
In the above example, val
is a proxy object that is aware of the container element. When NoProxy
is true
, one gets value semantics when indexing, resulting in a copy on each index access.
val = c[i] # val is a copy.
c[i].m() # Modify a copy of c[i].
assert(val == c[i]) # These have the same state because c[i] returns a new copy.
val.m()
assert(val != c[i]) # These do not have the same state.
当不使用代理时,仅当在对元素的引用上调用(例如在迭代过程中)时,元素的突变才会持续存在:
When proxies are not used, the mutations to the elements will only persists when invoked on a reference to the element, such as during iteration:
for val in c:
val.m() # modification observed in c[#]
当调用print(c[i])
时,将创建一个临时代理对象并将其传递给print
,并且该代理对象的生存期在从print()
返回时结束.因此,可以重新使用临时代理对象使用的存储器和标识.这可能导致元素看起来具有相同的标识:
When invoking print(c[i])
, a temporary proxy object is created and passed to print
, and the lifetime of the proxy object ends upon returning from print()
. Hence, the memory and identification used by the temporary proxy object may be re-used. This can result in elements appearing to have the same identification:
id0 = id(c[0]) # id of the temporary proxy
id1 = id(c[1]) # id of another temporary proxy
assert(id0 ?? id1) # Non-deterministic if these will be the same.
assert(c[0] is not c[1]) # Guaranteed to not be the same.
另一方面,在代理的生存期内,同一元素的其他代理将具有相同的标识,而不同元素的代理将具有不同的标识:
On the other hand, during the lifetime of a proxy, other proxies to the same element will have identical identification, and proxies to different elements will have different identification:
c0 = c[0] # proxy to element 0.
c0_2 = c[0] # another proxy to element 0.
c1 = c[1] # proxy to element 1
assert(c0 is c0_2)
assert(c0 is c[0])
assert(c0 is not c1)
在T
被暴露为由T*
持有的情况下,如果没有const T*
到Python对象的Python转换,则std::vector<const T*>
上的迭代将在Python中失败.将类T
公开为由T*
持有,将为T*
(而不是const T*
)注册自动到Python和从Python的转换.在Python中遍历集合时,将返回对元素的引用,导致无法从const T*
构造Python对象.另一方面,当通过索引访问元素时,生成的Python对象是代理或副本,可以使用现有的转换器.要解决此问题,请考虑以下任一方法:
In the situation where T
has been exposed as being held by T*
, iteration over std::vector<const T*>
will fail in Python if there is no to-Python conversion for const T*
to a Python object. Exposing class T
as being held by T*
registers automatic to-Python and from-Python conversions for T*
, not const T*
. When iterating over the collection in Python, references to elements are returned, resulting in a Python object failing to be constructed from a const T*
. On the other hand, when accessing elements via index, the resulting Python object is either a proxy or a copy, which can use the existing converters. To resolve this, consider either:
-
std::vector<>
的元素类型与T
的保留类型相同 - 明确注册
const T*
至Python转换器
- having
std::vector<>
's element type be the same asT
's held type - explicitly registering a
const T*
to-Python converter
这篇关于vector_indexing_suite返回的奇怪对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!