python函数单向传递 python函数值传递和引用传递( 二 )


2. sum = 0
3. if len(arg) == 0: return 0
4. else:
5. for x in arg.itervalues():
6. sum += x
7. return sum
那么对这个函数的调用可以用addOn()或诸如addOn(x=4,y=5,k=6)等的方式调用 。
上面说了四种函数形式定义的方式以及他们的调用方式 , 是分开说的 , 其实这四种方式可以组合在一起形成复杂多样的形参定义形式 。在定义或调用这种函数时 , 要遵循以下规则:
1. arg=value必须在arg后
2. *arg必须在arg=value后
3. **arg必须在*arg后
在函数调用过程中,形参赋值的过程是这样的:
首先按顺序把“arg”这种形式的实参给对应的形参
第二,把“arg=value”这种形式的实参赋值给形式
第三,把多出来的“arg”这种形式的实参组成一个tuple给带一个星号的形参
第四 , 把多出来的“key=value”这种形式的实参转为一个dictionary给带两个星号的形参 。
例子:
1. def test(x,y=5,*a,**b):
2. print x,y,a,b
就这么一个简单函数,来看看下面对这个函数调用会产生什么结果:
test(1) === 1 5 () {}
test(1,2) === 1 2 () {}
test(1,2,3) === 1 2 (3,) {}
test(1,2,3,4) === 1 2 (3,4)
test(x=1) === 1 5 () {}
test(x=1,y=1) === 1 1 () {}
test(x=1,y=1,a=1) === 1 1 () {'a':1}
test(x=1,y=1,a=1,b=1) === 1 1 () {'a':1,'b':1}
test(1,y=1) === 1 1 () {}
test(1,2,y=1) === 出错,说y给赋了多个值
test(1,2,3,4,a=1) === 1 2 (3,4) {'a':1}
test(1,2,3,4,k=1,t=2,o=3) === 1 2 (3,4) {'k':1,'t':2,'o':3}
Python 的函数是怎么传递参数的对象vs变量
在python中python函数单向传递 , 类型属于对象python函数单向传递,变量是没有类型的 , 这正是python的语言特性,也是吸引着很多pythoner的一点 。所有的变量都可以理解是内存中一个对象的“引用”,或者,也可以看似c中void*的感觉 。所以 , 希望大家在看到一个python变量的时候,把变量和真正的内存对象分开 。
类型是属于对象的,而不是变量 。
这样,很多问题就容易思考了 。
例如:
对象vs变量
12
nfoo = 1#一个指向int数据类型的nfoo(再次提醒 , nfoo没有类型)lstFoo = [1]#一个指向list类型的lstFoo,这个list中包含一个整数1
可更改(mutable)与不可更改(immutable)对象
对应于上一个概念,就必须引出另了另一概念 , 这就是可更改(mutable)对象与不可更改(immutable)对象 。
对于python比较熟悉的人们都应该了解这个事实,在python中,strings, tuples, 和numbers是不可更改的对象,而list,dict等则是可以修改的对象 。那么,这些所谓的可改变和不可改变影响着什么呢?
可更改vs不可更改
12345
nfoo = 1nfoo = 2lstFoo = [1]lstFoo[0] = 2
代码第2行中,内存中原始的1对象因为不能改变,于是被“抛弃”,另nfoo指向一个新的int对象,其值为2
代码第5行中,更改list中第一个元素的值 , 因为list是可改变的,所以,第一个元素变更为2 。其实应该说,lstFoo指向一个包含一个对象的数组 。赋值所发生的事情,是有一个新int对象被指定给lstFoo所指向的数组对象的第一个元素,但是对于lstFoo本身来说,所指向的数组对象并没有变化 , 只是数组对象的内容发生变化了 。这个看似void*的变量所指向的对象仍旧是刚刚的那个有一个int对象的list 。
如下图所示:
Python的函数参数传递:传值?引用?
对于变量(与对象相对的概念),其实 , python函数参数传递可以理解为就是变量传值操作,用C++的方式理解,就是对void*赋值 。如果这个变量的值不变,我们看似就是引用,如果这个变量的值改变 , 我们看着像是在赋值 。有点晕是吧 , 我们仍旧据个例子 。

推荐阅读