如何在 python 中修改 Python 变量的值(如引用)
How to modify the value of a Python variable(like a refrence) in python
我正在为 python 编写一个系统调用包装器(作为一个有趣的项目让我习惯 API),
当我开始实施 read() ,我对如何修改发送到我的函数的 python 缓冲区感到困惑。
该函数是 read() 系统调用的简单 cpython 包装器。
它需要一个整数(文件描述符)、一个缓冲区和您要读取的最大值,然后是 returns 读取的数量。
除了缓冲区的修改之外,我的一切都正常工作:
py_obj py_read(py_obj self, py_obj args){
char* buff;
int fd;
int len;
if(!PyArg_ParseTuple(args, "isi", &fd, &buff, &len)){
return NULL;
}
return Py_BuildValue("i", read(fd, buff, len));
}
加载模块后调用read:
>> from syscalls import read
>> STDIN = 1
>> s = ""
>> read(STDIN,s, 256)
napkin
7
>> s
""
虽然这是我所期望的(并且应该发生,因为我没有对参数的实际引用),但我想知道如何获取对参数的引用。
编辑:
使用@user2357112后,依然没有修改值
>>> b = memoryview(b"")
>>> from syscalls import *
>>> read(1, b, 10)
test
5
>>> b
<memory at 0x7fa060628408>
>>> b.tolist()
[]
>>>
编辑 2:
但它确实适用于 bytearray,如果我正确调整它的大小
谢谢@user2357112
您有对参数的引用。事实上,您可能刚刚破坏了参数对象或它周围的内存。您没有对调用者的 s
变量的引用,但是变量和引用无论如何都不像 Python 那样工作;引用总是引用对象。
Python 字符串对象不适合用作可变缓冲区。毕竟,它们应该是不可变的。此外,它们是 Unicode,并且 read
读取字节。相反,请使用具有 y*
格式代码的适当大小的 bytearray
and view its contents through a Py_buffer
结构。
此外,由于 read
returns ssize_t
而不是 int
,您应该使用 n
格式代码而不是 i
。 n
对应Py_ssize_t
,目的是在ssize_t
存在的情况下匹配ssize_t
。
PyObject *my_read(PyObject *self, PyObject *args){
Py_buffer buff;
int fd;
int len;
if(!PyArg_ParseTuple(args, "iy*i", &fd, &buff, &len)){
return NULL;
}
ssize_t read_count = read(fd, buff.buf, len);
PyBuffer_Release(&buff);
return Py_BuildValue("n", read_count);
}
我正在为 python 编写一个系统调用包装器(作为一个有趣的项目让我习惯 API),
当我开始实施 read() ,我对如何修改发送到我的函数的 python 缓冲区感到困惑。
该函数是 read() 系统调用的简单 cpython 包装器。
它需要一个整数(文件描述符)、一个缓冲区和您要读取的最大值,然后是 returns 读取的数量。
除了缓冲区的修改之外,我的一切都正常工作:
py_obj py_read(py_obj self, py_obj args){
char* buff;
int fd;
int len;
if(!PyArg_ParseTuple(args, "isi", &fd, &buff, &len)){
return NULL;
}
return Py_BuildValue("i", read(fd, buff, len));
}
加载模块后调用read:
>> from syscalls import read
>> STDIN = 1
>> s = ""
>> read(STDIN,s, 256)
napkin
7
>> s
""
虽然这是我所期望的(并且应该发生,因为我没有对参数的实际引用),但我想知道如何获取对参数的引用。
编辑: 使用@user2357112后,依然没有修改值
>>> b = memoryview(b"")
>>> from syscalls import *
>>> read(1, b, 10)
test
5
>>> b
<memory at 0x7fa060628408>
>>> b.tolist()
[]
>>>
编辑 2: 但它确实适用于 bytearray,如果我正确调整它的大小 谢谢@user2357112
您有对参数的引用。事实上,您可能刚刚破坏了参数对象或它周围的内存。您没有对调用者的 s
变量的引用,但是变量和引用无论如何都不像 Python 那样工作;引用总是引用对象。
Python 字符串对象不适合用作可变缓冲区。毕竟,它们应该是不可变的。此外,它们是 Unicode,并且 read
读取字节。相反,请使用具有 y*
格式代码的适当大小的 bytearray
and view its contents through a Py_buffer
结构。
此外,由于 read
returns ssize_t
而不是 int
,您应该使用 n
格式代码而不是 i
。 n
对应Py_ssize_t
,目的是在ssize_t
存在的情况下匹配ssize_t
。
PyObject *my_read(PyObject *self, PyObject *args){
Py_buffer buff;
int fd;
int len;
if(!PyArg_ParseTuple(args, "iy*i", &fd, &buff, &len)){
return NULL;
}
ssize_t read_count = read(fd, buff.buf, len);
PyBuffer_Release(&buff);
return Py_BuildValue("n", read_count);
}