扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
题主好. 如果不用 return, 我们可以选择利用传递参数的引用来『把值送出来』, 但这样只能针对不变对象, 如字典, 列表, numpy 数组等等. 例如我们可以用如下代码修改 numpy 数组:
创新互联建站专注于三门企业网站建设,成都响应式网站建设公司,商城网站开发。三门网站建设公司,为三门等地区提供建站服务。全流程按需网站制作,专业设计,全程项目跟踪,创新互联建站专业和态度为您提供的服务
mat = numpy.zeros((3,3))
compute_matrix( mat )
我们可以定义函数 compute_matrix 来修改参数 mat 的值, 并在这个函数结束后返回, 可以不用 return.
附录:
python 参数传递 (传值或传引用). 这篇博文将 python 中参数传递的情况, 什么时候传值什么时候传引用, 解释地很清楚, 具体地:
如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值--相当于通过“传引用”来传递对象。
如果函数收到的是一个不可变对象(比如数字、字符或者元组)的引用,就不能直接修改原始对象--相当于通过“传值'来传递对象。
Python中函数参数的传递是通过“赋值”来传递的。但这条规则只回答了函数参数传递的“战略问题”,并没有回答“战术问题”,也就说没有回答怎么赋值的问题。函数参数的使用可以分为两个方面,一是函数参数如何定义,二是函数在调用时的参数如何解析的。而后者又是由前者决定的。函数参数的定义有四种形式:
1. F(arg1,arg2,...)
2. F(arg2=value,arg3=value...)
3. F(*arg1)
4. F(**arg1)
第1 种方式是最“传统”的方式:一个函数可以定义不限个数参数,参数(形式参数)放在跟在函数名后面的小括号中,各个参数之间以逗号隔开。用这种方式定义的函数在调用的时候也必须在函数名后的小括号中提供相等个数的值(实际参数),不能多也不能少,而且顺序还必须相同。也就是说形参和实参的个数必须一致,而且想给形参1的值必须是实参中的第一位,形参与实参之间是一一对应的关系,即“形参1=实参1 形参2=实参2...”。很明显这是一种非常不灵活的形式。比如:"def addOn(x,y): return x + y",这里定义的函数addOn,可以用addOn(1,2)的形式调用,意味着形参x将取值1,主将取值2。addOn(1,2,3)和addOn (1)都是错误的形式。
第2种方式比第1种方式,在定义的时候已经给各个形参定义了默认值。因此,在调用这种函数时,如果没有给对应的形式参数传递实参,那么这个形参就将使用默认值。比如:“def addOn(x=3,y=5): return x + y”,那么addOn(6,5)的调用形式表示形参x取值6,y取值5。此外,addOn(7)这个形式也是可以的,表示形参x取值7,y取默认值5。这时候会出现一个问题,如果想让x取默认值,用实参给y赋值怎么办?前面两种调用形式明显就不行了,这时就要用到Python中函数调用方法的另一大绝招 ──关健字赋值法。可以用addOn(y=6),这时表示x取默认值3,而y取值6。这种方式通过指定形式参数可以实现可以对形式参数进行“精确攻击”,一个副带的功能是可以不必遵守形式参数的前后顺序,比如:addOn(y=4,x=6),这也是可以的。这种通过形式参数进行定点赋值的方式对于用第1种方式定义的函数也是适用的。
上面两种方式定义的形式参数的个数都是固定的,比如定义函数的时候如果定义了5个形参,那么在调用的时候最多也只能给它传递5个实参。但是在实际编程中并不能总是确定一个函数会有多少个参数。第3种方式就是用来应对这种情况的。它以一个*加上形参名的方式表示,这个函数实际参数是不一定的,可以是零个,也可以是N个。不管是多少个,在函数内部都被存放在以形参名为标识符的tuple中。比如:
对这个函数的调用addOn() addOn(2) addOn(3,4,5,6)等等都是可以的。
与第3种方式类似,形参名前面加了两个*表示,参数在函数内部将被存放在以形式名为标识符的dictionary中。这时候调用函数必须采用key1=value1、key2=value2...的形式。比如:
1. def addOn(**arg):
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教程
值传递(passl-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放
进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函
数的实参变量的值。
引用传递(pass-by-reference)过程中,被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函
数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正
因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。
更多技术请关注Python视频教程。
Python对可变对象(字典或列表)传址,
对不可变对象(数字、字符或元祖)传值。
那要看数据类型了,int,float,str这种就是传值,list,dict,类的实例,自定义对象都是穿引用。
下面是示例代码:
def change(int1,float1,str1,dict1,obj1,list1):
int1+=1
float1+=1
str1+='changed'
dict1['none_exist_key']='none_exist_value'
obj1=None
list1.append('change')
class obj:
pass
int1=0
float1=0.0
str1='origin'
dict1={'key':'value'}
obj1=obj()
list1=['only_element']
print(int1)
print(float1)
print(str1)
print(dict1)
print(obj1)
print(list1)
change(int1,float1,str1,dict1,obj1,list1)
print('after change')
print(int1)
print(float1)
print(str1)
print(dict1)
print(obj1)
print(list1)
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流