我正在尝试编写一个程序来向A级学生说明通过引用调用和使用Python调用值之间的区别。我成功地将可变对象作为变量传递给函数,但发现我也可以使用ctypes库做同样的事情。
我不太明白它是如何工作的,因为ctype库中有一个函数byref()
,但它在我的例子中不起作用。但是,通过调用函数而不使用byref()
,它确实有效!
**我的工作代码
"""
Program to illustrate call by ref
"""
from ctypes import * #alloews call by ref
test = c_int(56) #Pytthon call by reference eg addres
t = 67 #Python call by value eg copy
#expects a ctypes argument
def byRefExample(x):
x.value= x.value + 2
#expects a normal Python variable
def byValueExample(x):
x = x + 2
if __name__ == "__main__":
print "Before call test is",test
byRefExample(test)
print "After call test is",test
print "Before call t is",t
byValueExample(t)
print "After call t is",t
问题:
将普通Python变量传递给byValueExample()
时,它按预期工作。函数参数t
的副本会更改,但标头中的变量 t
不会更改。但是,当我传递ctypes变量 test 时,local和header变量都会发生变化,因此它就像一个C指针变量。虽然我的程序有效,但我不确定byref()
函数在使用时如何以及为什么不起作用:
的 byRefExample(byref(test))
的
答案 0 :(得分:2)
Python既不使用“按引用调用”或“按值调用”,而是“逐个调用”。赋值给对象命名。
test = c_int(56)
t = 67
test
是一个ctypes.c_int
对象的名称,该对象在内部具有分配给value
对象的int
名称。
t
是int
对象的名称。
致电byRefExample(test)
时,x
是ctypes.c_int
引用的test
对象的另一个名称。
x.value = x.value + 2
上面将ctypes.c_int
对象中存储的'value'名称重新分配给具有不同值的全新 int
对象。由于value
是名称ctypes.c_int
和test
引用的相同 x
对象的属性,x.value
和{{1}指的是相同的值。
致电test.value
时,byValueExample(t)
是x
引用的int
对象的另一个名称。
t
以上内容将名称x = x + 2
重新分配给具有不同值的全新 x
对象。 int
和x
不再引用同一个对象,因此t
不会观察到更改。它仍然引用原始的t
对象。
您可以通过在不同时间点打印int
个对象来观察此情况:
id()
输出(带注释):
from ctypes import *
test = c_int(56)
t = 67
print('test id =',id(test))
print('t id =',id(t))
#expects a ctypes argument
def byRefExample(x):
print('ByRef x',x,id(x))
print('ByRef x.value',x.value,id(x.value))
x.value = x.value + 2
print('ByRef x.value',x.value,id(x.value))
print('ByRef x',x,id(x))
#expects a normal Python variable
def byValueExample(x):
print('ByVal x',x,id(x))
x = x + 2
print('ByVal x',x,id(x))
print("Before call test is",test,id(test))
print("Before call test is",test.value,id(test.value))
byRefExample(test)
print("After call test is",test.value,id(test.value))
print("After call test is",test,id(test))
print("Before call t is",t,id(t))
byValueExample(t)
print("After call t is",t,id(t))