Python函数参数整理

1. Python中的参函数参数传址还是传值?

在其他语言(C/C++等)中函数参数有传地址或传值的说法。具体就是如果是传地址形式,那么在函数中修改参数的值,将影响到实参的值,而传值形式,则在函数中修改参数的值将不会影响到实参的值,因为函数中参数是实参的拷贝。那么在Python中有什么异同呢?看一个例子:

from ctypes import *
import os.path  
import sys

def test(c):
    print "test before "
    print ("c=%d" %c)
    print id(c)
    c+=2
    print "test after +"
    print ("c=%d" %c)
    print id(c)
    return c



a=2
print "main before call test"
print ("a=%d" %a)
print id(a)

print "####main before call test"

n=test(a)

print "main afterf call test"
print ("a=%d" %a)
print id(a)
print "####main after call test"

输出为:

main before call test
a=2
28499024
####main before call test
test before 
c=2
28499024
test after +
c=4
28498976
main afterf call test
a=2
28499024
####main after call test
[root@localhost python]# 

我结合输出解析下例子。

1) 输出为a=2,因为我们开始将a赋值为2

2)a的id为28499024,这个没什么好说的

3)进入test函数,c=2,id为28499024,跟a一样,说明是将a和c是同一个对象,这里看其实是传了地址

4)做加法运算后,c=4,id为28498976,已经改变了

5)回到main函数,a=2,id为28499024,没有改变

通过这个例子说明,Python函数传递方式是地址传递,但是如果函数中试图对参数进行修改,将有新的对象接收修改后的值

上面例子是一个方面,我们再看下一个例子:

from ctypes import *
import os.path  
import sys

def test(c):
    print "test before "
    print c
    print id(c)
    c[0]+=2
    print "test after +"
    print c
    print id(c)
    return c

a=[1,2,3]
print "main before call test"
print a
print id(a)

print "####main before call test"

n=test(a)

print "main afterf call test"
print a
print id(a)
print "####main after call test"

输出为:

main before call test
[1, 2, 3]
139757398355408
####main before call test
test before 
[1, 2, 3]
139757398355408
test after +
[3, 2, 3]
139757398355408
main afterf call test
[3, 2, 3]
139757398355408
####main after call test
[root@localhost python]# 

前面没什么好解析的,传递到函数中的都是同一个对象,但是操作c[0]+=2后,并没有生成新的对象来接收操作值,而是原来的对象。从test函数返回后,打印的列表值,也受到了影响。

所以对于Python函数参数的传递形式,我们不能用C/C++等语言函数参数值传递/地址传递的方式去理解

在Python中参数类型有mutable(可变的) 和 inmutable (不可变的)

mutable : list(列表) ,dict(字典)

inmutable : int , string , float ,tuple...

参数传递到函数内部,对于可变类型,直接修改;对于不可变类型,用新的对象接收修改后的值。

其实,在函数参数传递,本质上还是赋值语句,在Python中,所谓赋值其实是传递引用,一旦对象进行修改,就会区分mutable(直接修改) inmutable (新建对象接收修改值),对于inmutable 对象,操作后发生变化,则由新的对象来承接。

如下:

a=2
b=3
c=[1,2]
print id(a)
print id(b)
print id(c)
a+=a
print id(a)
a+=a
print id(a)
a=b
print id(b)
a=c
print id(a)
print c
c[0]=3
print c
print id(c)

输出:

22486096
22486072
139734120213896
22486048
22485952
22486072
139734120213896
[1, 2]
[3, 2]
139734120213896
c赋值给a后,a和c指向同一个对象。才a(不可变)进行修改,生成新的对象来接收,a指向新的对象;对c(可变对象)进行修改,承接修改结果的还是c

2 Python中函数默认参数

先看个例子:

from ctypes import *
import os.path  
import sys
def f(x,l=[],arg=None):
    print id(l)
    print id(arg)
    for i in range(x):
        l.append(i*i)
    print(l)
    print id(l)
    print id(arg)
 
print('---1---')
f(4)
print('---2---')
f(5)
print('---3---')
f(5,[])

输出:

---1---
140259558485456
140259557097248
[0, 1, 4, 9]
140259558485456
140259557097248
---2---
140259558485456
140259557097248
[0, 1, 4, 9, 0, 1, 4, 9, 16]
140259558485456
140259557097248
---3---
140259558482792
140259557097248
[0, 1, 4, 9, 16]
140259558482792
140259557097248
[root@localhost python]# 

可以看到对于有默认参数的函数,如果有传递参数,则用传递的参数替换,如果没有则使用默认的参数,需要注意的是:对于mutable(可变参数),每次不传递参数的调用都将使用同一个对象,所以一般是不建议将mutable(可变参数)设置为默认参数的

3 可变参数args和kargs

惯例先看例子:

from ctypes import *
import os.path  
import sys

def test(*args,**kargs):
	print type(args)
	print id(args)
	print args
	print type(kargs)
	print id(kargs)
	print kargs


	
test("aaaa","bbbb","cccc",aaaa="aaaa",bbbb="bbbb")
print "*"*100
test("a","b","c",a="a",b="b")

输出:

<type 'tuple'>
140355262179120
('aaaa', 'bbbb', 'cccc')
<type 'dict'>
25255472
{'aaaa': 'aaaa', 'bbbb': 'bbbb'}
****************************************************************************************************
<type 'tuple'>
140355262179120
('a', 'b', 'c')
<type 'dict'>
25255472
{'a': 'a', 'b': 'b'}

结合输出和代码我们可以得到:

1) args本质上是tuple(元组),kargs本质上是dict(字典)

2)tuple不可修改,但是两次调用显示的args的id是一样的

我们做下面修改(返回args):

from ctypes import *
import os.path  
import sys

def test(*args,**kargs):
	print type(args)
	print id(args)
	print args
	print type(kargs)
	print id(kargs)
	print kargs
	return args

	
aa = test("aaaa","bbbb","cccc",aaaa="aaaa",bbbb="bbbb")
print id(aa)
print "*"*100
bb = test("a","b","c",a="a",b="b")
print id(bb)

输出:

<type 'tuple'>
140463185413936
('aaaa', 'bbbb', 'cccc')
<type 'dict'>
27319728
{'aaaa': 'aaaa', 'bbbb': 'bbbb'}
140463185413936
****************************************************************************************************
<type 'tuple'>
140463185414816
('a', 'b', 'c')
<type 'dict'>
27319728
{'a': 'a', 'b': 'b'}
140463185414816

再做下面修改(返回kargs):

from ctypes import *
import os.path  
import sys

def test(*args,**kargs):
	print type(args)
	print id(args)
	print args
	print type(kargs)
	print id(kargs)
	print kargs
	return kargs


	
aa = test("aaaa","bbbb","cccc",aaaa="aaaa",bbbb="bbbb")
print id(aa)
print type(aa)
print "*"*100
bb = test("a","b","c",a="a",b="b")
print id(bb)
print type(bb)

输出:

<type 'tuple'>
139682381502256
('aaaa', 'bbbb', 'cccc')
<type 'dict'>
26025360
{'aaaa': 'aaaa', 'bbbb': 'bbbb'}
26025360
<type 'dict'>
****************************************************************************************************
<type 'tuple'>
139682381502256
('a', 'b', 'c')
<type 'dict'>
25269056
{'a': 'a', 'b': 'b'}
暂时还不知道解释,后面再看看~


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值