python的传参特性

1、传递参数一般有两种方式:引用和传递值。
严格的定义不上了,口语表达为:
引用:子函数直接修改所在地址的值
值传递:将子函数的返回值复制出来并返回
举例:使用过C++的朋友应该知道Cpp中对引用传参和值传参的定义,如 int(a) 和 void(&a)的区别:
值传参是将局部函数中的值复制成一个新的地址传递到主函数中,而引用传参是将主函数的参数地址直接给到子函数,子函数在该内存地址上对内存的值直接操作,举例如下:
如下的C++语句:

#include <iostream>
using namespace std;
int main()
{
    int plus1(int);
    void plus2(int &);
   int b=1;
   cout<<" plus1" <<endl;
   plus1(b);
   //运行不改变b的值
   cout<<"plus1 run   b= "<<b<<endl;
   cout<<" plus2  "<<endl;
   plus2(b);
   //直接改变b的值
   cout<<"plus2 run   b= "<<b<<endl;
   plus2(b);
   //直接改变b的值
   cout<<"plus2 run   b= "<<b<<endl;
}
int plus1(int a){
a+=1;
return a;

}

void plus2(int&a){
a=a+1;
}

在上面的代码块中,int plus1() 用的是值传递参数,void plus2() 用的是引用传递参数。运行的结果:

plus1
plus1 run   b= 1
 plus2
plus2 run   b= 2
plus2 run   b= 3
Process returned 0 (0x0)   execution time : 0.062 s
Press any key to continue.

可以看到,在运行plus1之后,虽然有返回值,但是主函数中的b是不改变的,因此在plus1()运行后,b仍然是1,但是在plus2运行之后,b的值直接加上了1,plus2用的就是引用的传参特性。
总结:引用传参直接改变参数的值,值传参不改变主函数中参数的值。

当然,如果想让plus1()也有加1的功能也很简单。将主函数第5行改成:

b=plus1(b);

修改后:
整体代码块为:

#include <iostream>
using namespace std;
int main()
{
    int plus1(int);
    void plus2(int &);
   int b=1;
   cout<<" plus1" <<endl;
   b=plus1(b);
   //运行不改变b的值
   cout<<"plus1 run   b= "<<b<<endl;
   cout<<" plus2  "<<endl;
   plus2(b);
   //直接改变b的值
   cout<<"plus2 run   b= "<<b<<endl;
   plus2(b);
   //直接改变b的值
   cout<<"plus2 run   b= "<<b<<endl;
}
int plus1(int a){
a+=1;
return a;

}

void plus2(int&a){
a=a+1;
}

运行结果为:

 plus1
plus1 run   b= 2
 plus2
plus2 run   b= 3
plus2 run   b= 4

Process returned 0 (0x0)   execution time : 0.031 s
Press any key to continue.

以上是cpp中传参的用法,但是对于python这种解释性语言而言,没有像cpp这样严密的传参方式定义。它的传参方式又是怎么样的呢。

2、python中的引用传参和值传参特性
直接上结论:
对于可变对象,python是用的引用传参,指字典、列表等可变对象
对于不可变对象,python用的值传参,指数字,字符,元组

上一个python中经典的误用:

def fuc(a,b=[]):
    b.append(a)
if __name__=="__main__":
    b=[]
    fuc(2,b)
    print (b)
    fuc(3,b)
    print(b)

该段代码的目的是为了将a中的元素复制到list b 中,代码希望fuc(a,b) 时,输出的结果时b=[a]
即我们希望运行的结果是:

[2]
[ 3]

然而,实际运行时发现结果为:

[2]
[2, 3]

在fuc(3,b)中竟然输出的b还保留了2的值。
这里就是引用传参在作怪,由于python对于列表时引用传参。在调用fuc(2,b)时,b的值已经被改变成[2].因此在再次调用fuc(3,b)时,b的值时在[2]的基础上在末尾加上了3.即 b=[2 3]
而要想避免以上情况,也很简单。将函数改为:

def fuc(a,b=[]):
    b.clear()
    b.append(a)
    print(f'a={a}')
    print(f'b={b}')
    print(id(b),'in fuc ')
    
if __name__=="__main__":
    b=[]
    print(id(b),'before fuction')
    fuc(2,b)
    print(f'b in main fuction 1:  {b}')
    print(id(b),'in main fuction 1')
    fuc(3,b) 
    print(f'b in main fuction 2:  {b}')
    print(id(b),'in main fuction 2')

即在每次的调用中,都先将b clear 掉。
查看,在子函数中地址和主函数的b的地址:

1783220742600 before fuction
a=2
b=[2]
1783220742600 in fuc 
b in main fuction 1:  [2]
1783220742600 in main fuction 1
a=3
b=[3]
1783220742600 in fuc 
b in main fuction 2:  [3]
1783220742600 in main fuction 2

发现b的内存地址在fuc 操作后仍然保持一致,即fuc中的操作是直接修改主函数中b的值

而对于符号变量,python使用的是值传参

def fuc2(a):
    print(id(a),'in fuc2')
    a=3
    print(id(a),'in fuc2  after')
    return a
    
if __name__=="__main__":
    a=0
    print(id(a),'in main function')
    fuc2(a)

运行结果:

1359440928 in main function
1359440928 in fuc2
1359441024 in fuc2  after

发现在 fuc2操作后,a的内存地址是在局部函数fuc2中新开辟的。

a
Out[28]: 0

a没有改变。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值