需求介绍
写一段程序,交换两个数的位置。
初步分析
那必然把功能写成函数,然后主程序调用函数,这样的好处是:实现代码复用。
def exchange(number1,number2):
temp = number1
number1 = number2
number2 = temp
调用部分如下代码:
min = int(input("enter the min number :"))
max = int(input("enter the max number :"))
print("Before: num1 = {0} and num2 = {1}".format(min,max))
exchange(min,max)
print("After: num1 = {0} and num2 = {1}".format(min,max))
ok,万事俱备,只差bug,哦不不不,万事俱备,只差结果。
enter the min number :14
enter the max number :54
Before: num1 = 14 and num2 = 54
After: num1 = 14 and num2 = 54
怎么事儿?不给面儿啊!这结果明显不对啊!
进一步分析
心机蛙一直摸你肚子,这个定义的temp值是局部的,所以交换只在函数内部其作用,那我把print函数写到函数内部不就完了吗?
def exchange(number1,number2):
temp = number1
number1 = number2
number2 = temp
print("After: num1 = {0} and num2 = {1}".format(number1, number2))
来看一下效果:
enter the min number :14
enter the max number :54
Before: num1 = 14 and num2 = 54
After: num1 = 54 and num2 = 14
ok,对味儿了。但是为什么呢?
原因分析
这里面调换来调换去,肯定是把number1和number2的位置给互换了的,但是为什么不能输出出来这个调换后的结果呢?
答案是,调换只在函数内部,出了函数人家就不认了,说到底还是局部变量的局限性,那既然他这么局限,我们就用全局的呗
def exchange(number1,number2):
global min,max
temp = number1
min = number1 = number2
max = number2 = temp
看下结果:
enter the min number :14
enter the max number :54
Before: num1 = 14 and num2 = 54
After: num1 = 54 and num2 = 14
ok,符合预期。
进一步思考
这个例子很明显是引用了实参值(实参和形参的区别请看这位博主https://blog.csdn.net/weixin_39269366/article/details/120453021),牵扯到引用的问题,就毫不意外地提一嘴值传递和引用传递(值传递与引用传递的区别请看这位博主
https://blog.csdn.net/mengfanshaoxia/article/details/121128992)。
简单来说,值传递就是把值复制一份,交换函数的操作是在备份的文件操作,而主函数打印对象还是再原来那份数据进行操作,两者作用的对象都不一样了,怎么可能打印正确结果呢?
而引用传递可以认为是地址引用,直接把地址传过去了,那交换函数的操作对象和主函数的操作对象都是地址所指向的这份数据,当然也就符合预期了。
拓展
交换两个数的位置,不一定非去设置中间变量来回倒水,还可以用一些数学的方法,
比如:
a = a * b , b = a / b, a = a / b
再比如:
a = a + b,b = a - b , a = a - b
……
也可以用一些逻辑运算(具体原因参考:这轮提问https://www.zhihu.com/question/57945220):
比如:
a = a ^ b, b = a ^ b ,a = a ^ b
……
当然,还有其他创新的方法,这里不再一一列举。
完结撒花
其实这个问题应该是学习数据结构时候最基础的一个问题,但是当时肯定想不到这么多的解法,我们成长的过程其实就是从“借个杯子来回倒水完成交换”到“算术、逻辑、引用……来完成交换”,大部分时候问题不会变,只是人成长了,人类文明进步了。
尽心求索,一心为学。