vector_indexing_suite 返回的奇怪对象
weird object returned by vector_indexing_suite
我有一个
std::vector<const T*>
我 return 来自 c++ 函数:
getallTs()
我已经将 T class 暴露为:
class_<T,T*>
向量像这样:
class_<std::vector<const T*> >("TsList")
.def(vector_indexing_suite<std::vector<const T*>,true>())
;
NoProxy 参数是什么意思?
我这样公开函数:
def("getallTs", getallTs,
return_value_policy<return_by_value>{});
我观察到一个奇怪的行为。
当我从 python
打电话时
tlist = getallTs()
我得到一个 TsList 对象。
len(tlist)
有效。
tlist[<anycorrectindex>].<someattribute>
也有效。
但是,如果我只是
print(tlist[0])
和
print(tlist[100])
python 打印
object T at <address>
这个地址对于tlist中的所有T都是一样的。
此外,我无法使用 python for 循环遍历 Tlist。
for t in tlist:
不起作用。
知道我将向量和函数公开给 python 的方式有什么问题吗?
我理解 python 每个包装 C++ T 的对象都有一个指向 T 的原始指针。
这些 T 实例在整个过程中以全局 table.
的形式存在
C++ 函数返回指向这些实例的指针向量。
indexing_suite 用这些做什么?
谢谢,
当通过索引访问元素时,索引套件默认为元素提供代理,作为一种为可变类型提供引用语义的方法,Python 用户通常希望使用集合:
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
时,在索引时获取值语义,从而在每次索引访问时生成一个副本。
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.
当不使用代理时,元素的变化只会在对元素的引用被调用时持续存在,例如在迭代期间:
for val in c:
val.m() # modification observed in c[#]
调用print(c[i])
时,会创建一个临时代理对象并传递给print
,代理对象的生命周期在从print()
返回时结束。因此,可以重新使用临时代理对象使用的内存和标识。这可能导致元素看起来具有相同的标识:
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.
另一方面,在代理的生命周期内,同一元素的其他代理将具有相同的标识,而不同元素的代理将具有不同的标识:
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*
的情况下,如果没有 to-[=,对 std::vector<const T*>
的迭代将在 Python 中失败53=] 将 const T*
转换为 Python 对象。将 class T
公开为由 T*
持有会自动注册到-Python 和从-Python 的转换 T*
,而不是 const T*
.当遍历 Python 中的集合时,返回对元素的引用,导致无法从 const T*
构造 Python 对象。另一方面,当通过索引访问元素时,生成的 Python 对象是代理或副本,可以使用现有的转换器。要解决此问题,请考虑:
std::vector<>
的元素类型与T
的持有类型相同
- 显式注册一个
const T*
到-Python 转换器
我有一个
std::vector<const T*>
我 return 来自 c++ 函数:
getallTs()
我已经将 T class 暴露为:
class_<T,T*>
向量像这样:
class_<std::vector<const T*> >("TsList")
.def(vector_indexing_suite<std::vector<const T*>,true>())
;
NoProxy 参数是什么意思?
我这样公开函数:
def("getallTs", getallTs,
return_value_policy<return_by_value>{});
我观察到一个奇怪的行为。
当我从 python
打电话时tlist = getallTs()
我得到一个 TsList 对象。
len(tlist)
有效。
tlist[<anycorrectindex>].<someattribute>
也有效。
但是,如果我只是
print(tlist[0])
和
print(tlist[100])
python 打印
object T at <address>
这个地址对于tlist中的所有T都是一样的。
此外,我无法使用 python for 循环遍历 Tlist。
for t in tlist:
不起作用。
知道我将向量和函数公开给 python 的方式有什么问题吗?
我理解 python 每个包装 C++ T 的对象都有一个指向 T 的原始指针。 这些 T 实例在整个过程中以全局 table.
的形式存在C++ 函数返回指向这些实例的指针向量。 indexing_suite 用这些做什么?
谢谢,
当通过索引访问元素时,索引套件默认为元素提供代理,作为一种为可变类型提供引用语义的方法,Python 用户通常希望使用集合:
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
时,在索引时获取值语义,从而在每次索引访问时生成一个副本。
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.
当不使用代理时,元素的变化只会在对元素的引用被调用时持续存在,例如在迭代期间:
for val in c:
val.m() # modification observed in c[#]
调用print(c[i])
时,会创建一个临时代理对象并传递给print
,代理对象的生命周期在从print()
返回时结束。因此,可以重新使用临时代理对象使用的内存和标识。这可能导致元素看起来具有相同的标识:
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.
另一方面,在代理的生命周期内,同一元素的其他代理将具有相同的标识,而不同元素的代理将具有不同的标识:
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*
的情况下,如果没有 to-[=,对 std::vector<const T*>
的迭代将在 Python 中失败53=] 将 const T*
转换为 Python 对象。将 class T
公开为由 T*
持有会自动注册到-Python 和从-Python 的转换 T*
,而不是 const T*
.当遍历 Python 中的集合时,返回对元素的引用,导致无法从 const T*
构造 Python 对象。另一方面,当通过索引访问元素时,生成的 Python 对象是代理或副本,可以使用现有的转换器。要解决此问题,请考虑:
std::vector<>
的元素类型与T
的持有类型相同- 显式注册一个
const T*
到-Python 转换器