Understanding Python's call-by-object style of passing function arguments
我不确定我是否理解python的按对象调用的概念,即传递函数参数的风格(在这里解释http://effbot.org/zone/call by object.htm)。似乎没有足够的例子来很好地阐明这个概念(或者我的google fu可能很弱!)D)
我编写了这个小的人为的python程序来试图理解这个概念。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | def foo( itnumber, ittuple, itlist, itdict ): itnumber +=1 print id(itnumber) , itnumber print id(ittuple) , ittuple itlist.append(3.4) print id(itlist) , itlist itdict['mary'] = 2.3 print id(itdict), itdict # Initialize a number, a tuple, a list and a dictionary tnumber = 1 print id( tnumber ), tnumber ttuple = (1, 2, 3) print id( ttuple ) , ttuple tlist = [1, 2, 3] print id( tlist ) , tlist tdict = tel = {'jack': 4098, 'sape': 4139} print '-------' # Invoke a function and test it foo(tnumber, ttuple, tlist , tdict) print '-------' #Test behaviour after the function call is over print id(tnumber) , tnumber print id(ttuple) , ttuple print id(tlist) , tlist print id(tdict), tdict |
程序的输出是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 146739376 1 3075201660 (1, 2, 3) 3075103916 [1, 2, 3] 3075193004 {'sape': 4139, 'jack': 4098} --------- 146739364 2 3075201660 (1, 2, 3) 3075103916 [1, 2, 3, 3.4] 3075193004 {'sape': 4139, 'jack': 4098, 'mary': 2.3} --------- 146739376 1 3075201660 (1, 2, 3) 3075103916 [1, 2, 3, 3.4] 3075193004 {'sape': 4139, 'jack': 4098, 'mary': 2.3} |
如您所见,除了传递的整数之外,对象ID(据我所知是指内存位置)保持不变。
所以在整数的情况下,它是(有效地)通过值传递的,其他数据结构是(有效地)通过引用传递的。我试图更改列表、数字和字典,以测试数据结构是否已更改到位。号码不在名单上字典是。
我在上面有效地使用了这个词,因为根据上面代码中传递的数据结构,参数传递的"按对象调用"样式似乎表现为两种方式。
对于更复杂的数据结构(比如numpy数组等),是否有快速的经验法则识别哪些参数将通过引用传递,哪些参数将通过值传递?
关键的区别在于,在C语言中,变量是内存中的一个框,用于放置内容。在python中,变量是一个名称。
python既不是按引用调用,也不是按值调用。这是更明智的做法!(事实上,我在学习更常见的语言之前就已经学习了Python,所以按值调用和参照调用对我来说很奇怪。)
在python中,有事物,也有名字。列表、整数、字符串和自定义对象都是。
1 | x = [] |
意思是"建造一个新的东西,命名为
1 2 3 | x = [] foo = lambda x: x.append(None) foo(x) |
意思是"用
1 2 3 4 | x = 0 def foo(x): x += 1 foo(x) |
意思是"在
其他人已经给出了很好的答案。我认为还有一件事会有所帮助:
1 | x = expr |
评估
1 | x.operate() |
对
有趣的案例包括:
1 | x += expr |
可译为
1 2 3 4 | >>> x = 1 >>> x += 2 >>> x 3 |
(所以
1 2 3 4 5 6 7 8 9 | >>> x = ([1], 2) >>> x ([1], 2) >>> x[0] += [3] Traceback (most recent call last): File"<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment >>> x ([1, 3], 2) |
在这里,
python中的数字、字符串和元组是不可变的;使用增强赋值将重新绑定名称。
您的其他类型仅仅是变异的,并且保持相同的对象。