1、参数的传递是通过自动将对象赋值给本地变量名来实现的。函数参数(调用者发送的(可能的)共享对象的引用值),所有的参数实际上都是通过指针进行传递的。作为参数被传递的对象从里不自动拷贝。
2、在函数内部的参数名的赋值不会影响调用者。在函数运行时,在函数头部的参数名是一个新的、本地变了,这个变量名时再函数的本地作用域内的。函数参数名和调用者作用域的变量名是没有别名的。
3、改变函数的可变对象的参数也许会对调用者有影响。换句话说,因为参数是简单的赋值给传入对象。函数能够就地的改变传入的可变对象,因此其结果影响调用者。可变参数对于函数来说是可以做输入和输出的。
4、不可变参数“通过值”进行拷贝的。像整数和字符串这样的对象通过对象引用而不是拷贝进行传递的,但是因为你无聊怎样都不可能在原处改变不可变对象,实际效果就很像创建一份拷贝。
5、可变对象是通过“指针”进行传递的。例如,列表和字典这样的对象也就是通过对象引用进行传递的,这点与C语言使用的指针传递数组很相似:可变对象那个在函数内部进行原处的改变,这一点和C数组很像。
例如:
def f(a,b):
a = 100
b[0]='spam'
x = 1
y = [1,2]
f(x,y)
print(x,y) #输出:100,['spam',2] 因为给a传递的是数字,数字不可变,但是b可以改变
6、参数传递的几种方式
位置:从左到右进行匹配。
关键字参数:通过参数名进行匹配
默认参数:为没有传入值的参数定义参数值
可变参数:手机任意多基于位置或者关键字的参数:(调用者能够再使用*语法去将参数集合打散,分成参数,这个*与在函数头部的*恰恰相反,在函数头部的它意味着收集任意多的参数,而在调用中意味着传递任意多的参数。)
Keywod-only参数:参数必须按照名称传递:(在python3.0中(不包括python2.6))函数也可以指定参数,参数必须用带有关键字参数的名字来传递。这样的参数通常用来地宫一实际参数以外配置选项。
7、例子:
func(value) 常规参数传递,通过位置进行匹配
func(name=value) 关键字参数,通过变量名匹配
func(*sequence) 以name传递所有对象,并作为独立的基于位置的参数
func(**dict) 以name成对的传递所有的关键字/值,并作为独立的关键字参数
def func(name) 常规参数:通过位置或变量名进行匹配
def func(name=value) 默认值参数,如果没有在调用者中传递的话
def func(*name) 匹配并收集在元祖中所包含位置参数
def func(**name) 匹配并收集在字典中的所有包含位置的参数
def func(*args,name) 参数必须在调用中按照关键字传递
def func(*,name=value) python3.0中有的
8、如果决定使用并混合特定的参数匹配模型,Python将会遵循下面有关 顺序法则。
(在函数调用中,参数必须以此属性出现:任何位置参数(value),后面跟着任何关键字参数(name=value)和*sequence像是的组合,后面跟着**dict形式)
(在函数头部,参数必须以此书序出现;任何一般参数(name),紧跟着任何默认参数(name=value),如果有的话,后面是*name(或者在python3.0中是*)形式,后面跟着任何name或者name=value kyeword-only(在python3.0中)后面跟着**name形式)
9、任意参数的实例
例如:
*
def f(*arg):print(arg)
f() #输出:()
f(1)#输出:(1,)
f(1,2,3,4,5)#输出:(1,2,3,4,5)
**能够对多余的关键字参数有效,将多余的关键字参数转化为字典。
def (**arg):print(arg)
f() #输出:{}
f(a=1,b=2) #输出:{’a':1,'b':2}
混合用法:
def f(a,*arg,**kargs):print(a,arg,kargs)
f(1,2,3,x=1,y=x) #输出:1,(2,3){'x':1,'y':2}
10、解包参数
*解包元祖,列表,集合,字符串
def func(a,b,c,d):print(a,b,c,d)
arg = (1,2)
arg += (3,4)
func(*args) #输出:1,2,3,4
**解包字典,使其成为独立的关键字参数(就是说键必须跟函数定义时的参数同名)
d = {'a':1,'b':2,'c':3,'d':4}
f(**d)#输出:1,2,3,4
#错误的:d = {'x':1,'y':2,'z':3,'t':4} f(**t) 会报错
11、python3.0 Keysword-Only关键字参数
语法:
keyword-onl参数编码为命名的参数,出现在参数列表*args之后,所有的这些参数必须在调用中使用关键字语法来传递。例如下面的代码:a可能按照名称或者位置传递,b可以收集任意额外的位置参数,并且C必须只按照关键字攒地
def f(a,*b,c):
print(a,b,c)
f(1,2,c=3) #输出;1 (2,) 3
f(a=1,c=3) #输出:1 () 3
#f(1,2,3) 报错
我们可以在参数列表中使用一个*字符,来表示一个函数不会接受一个变量长度参数列表,而仍然期待跟在*后面的所有字符都作为关键字传递。在下一个函数中,a可能再次按照位置或者名称传递,但是b和c必须按照关键字传递,不允许其他额外的位置传递
def f(a,*,b,c):
print(a,b,c)
f(1,c=3,b=2) #输出:1,2,3
f(c=3,b=2,a=1) #输出:1,2,3
#f(1,2,3) 和f(1)都会报错。
仍然可以对keyword——only参数使用默认值,即便他们出现在函数的头部中*后面,在下面的代码中,a可能按照名次或者位置传递,而b和c是可选的,但是如果使用的话必须按照关键字传递:
def f(a,*,b='spam',c='ham'):
print(a,b,c)
f(1) #输出:1,spam,ham
f(1,c=3) #输出:1,spam,3
f(a=1) #输出:1,spam,ham
f(c=3,a=1,b=2) #输出:1,2,3
12、keyword-only定义时排序规则
keyword-only参数必须在一个单个星号后面指定,而不是两个星号前。这意味着,在一个函数头部,keyword-only参数必须编写在**args关键字参数之前,且在*arg任意位置形式之后。当二者都有的时候,无论何时,一个参数名称出现在*args之前,它可能是默认位置参数,而不是keyword_only参数。
#错误的def f(a,*b,**d,c=6):print(a,b,c,d)
#正确的
def f(a,*b,c=6,**d):print(a,b,c,d)
f(1,2,3,x=4,y=5) #输出:1 (2,3) 6 {'x':4,'y':5}
f(1,2,3,x=4,y=5,c=7) #输出:1 (2,3) 7 {'x':4,'y':5}
f(1,2,3,c=7,x=4,y=5) #输出:1 (2,3) 7 {'x':4,'y':5}
但是最后一个不是keyword-only参数了
def f(a,c=6,*b,**d):print(a,b,c,d)
f(1,2,3,x=4) #输出:1 (3,) 2{'x':4}
13、keyword-only调用时排序规则
在函数调用中,当传递keyword-only参数的时候,他们必须出现在**args形式之前。keyword-only参数可以出现在*arg之前或者之后,也有可能包含在**arg中
def f(a,*b,c=6,**d)
14、模拟python3.0中的print函数
def print30(*args,**kargs):
sep = kargs.get('seq',' ')
end = kargs.get('end','\n')
file = kargs.get('file',sys.stdout)
output = ''
first = true
for arg in args:
output += ('' if first else sep))+str(arg)
first = false
file.write(output+end)