Python使用ctypes通过值调用值调用

时间:2013-08-09 17:34:31

标签: python

我正在尝试编写一个程序来向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))

1 个答案:

答案 0 :(得分:2)

Python既不使用“按引用调用”或“按值调用”,而是“逐个调用”。赋值给对象命名。

test = c_int(56)
t = 67

test是一个ctypes.c_int对象的名称,该对象在内部具有分配给value对象的int名称。

tint对象的名称。

致电byRefExample(test)时,xctypes.c_int引用的test对象的另一个名称。

x.value = x.value + 2

上面将ctypes.c_int对象中存储的'value'名称重新分配给具有不同值的全新 int对象。由于value是名称ctypes.c_inttest引用的相同 x对象的属性,x.value和{{1}指的是相同的值。

致电test.value时,byValueExample(t)x引用的int对象的另一个名称。

t

以上内容将名称x = x + 2 重新分配给具有不同值的全新 x对象。 intx不再引用同一个对象,因此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))