我相信以下两段代码应该等效:
df = (pd.DataFrame(d)
.stack()
.reset_index()
.rename({'level_0': 'Column2', 'level_1': 'Column1', 0: 'Column3'}, axis=1)
.sort_index(1).sort_values('Column1'))
print(df)
Column1 Column2 Column3
0 Jill Avenger: Age of Ultron 7.0
2 Jill Django Unchained 6.5
4 Jill Gone Girl 9.0
5 Jill Kill the Messenger 8.0
1 Toby Avenger: Age of Ultron 8.5
3 Toby Django Unchained 9.0
6 Toby Zoolander 2.0
两个代码都将打印“ H”。
我不了解的是第二个示例中的内存解除固定位置。
据我了解,字符串是在堆上分配的,// first example
string s = "Hello memmory";
ReadOnlyMemory<char> memory = s.AsMemory();
using (MemoryHandle pin = memory.Pin())
{
Span<char> span = new Span<char>(pin.Pointer, 1);
Console.WriteLine(span[0]);
}
// second example
ReadOnlySpan<char> span2 = memory.Span;
Console.WriteLine(span2[0]);
固定它并从指针创建Span。 MemoryHandle
解除锁定。
我相信MemoryHandle.Dispose
也必须固定内存,否则span无法访问指针。但是在第二个示例中如何取消固定内存?
答案 0 :(得分:1)
最后一个假设是错误的:memory.Span
不需要固定内存,因为垃圾回收器知道其底层引用。如果您希望将指针传递给本机API,则可以单独使用固定功能。
答案 1 :(得分:0)
Span仅驻留在当前方法线程的堆栈上,而不驻留在其方法的堆上,因此只要您在其中使用它,它就将一直存在。到目前为止很清楚。
现在有趣的部分:
一个清楚的事实是,memory.Span
的结果不是固定的,而仅是通过使用ref T
内的Span<T>
来引用的。 GarbageCollector。
只要您的记忆一直存在,您的跨度也将因此而跨度。
参考文献:
https://msdn.microsoft.com/en-us/magazine/mt814808.aspx?f=255&MSPPError=-2147217396 https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref#ref-struct-types