题外话:由于时间关系,没能保持必定的更新频率。但仍是会一直坚持的~数组
以前介绍了Python函数的定义,今天分享一下Python函数的参数吧!内容会有点多~app
Python的函数定义比较简单,借助于关键字def进行实现,可是参数的灵活度却很是大。除了正常定义的必选参数外,还可使用默认参数、可变参数、关键字参数、命名关键字参数以及参数组合,这使得函数定义出来的接口,不只能处理复杂的参数,还能简化调用者的代码。函数
例如:计算x的n次方ui
def powern(x,n): s = 1 while n >0: s = s * x n = n -1 return s
x与n这两个参数都是位置参数。调用函数时,必须传入且传入的两个值按照位置顺序依次赋给参数x和n,若缺省,则会报错。例如:code
>>> powern(5) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: powern() missing 1 required positional argument: 'n'
def powern( x,n = 3): s = 1 while n >0: s = s * x n = n -1 return s
执行:powern(2),至关于调用powern(2,3)
若是要求2的四次方,则须要执行:powern(2,4)对象
设置默认参数的好处?
默认参数能够简化函数的调用,下降调用函数的难度。不管是简单调用仍是复杂调用,函数只需定义一个。
例如上述powern()的例子,当传入n的其余值时,则能够实现x的其余n次方。接口
可是在使用默认参数的时候,若是使用不当,也会有坑。先来了解一下可变参数和不可变参数做为函数参数时的不一样:ip
>>> a = 1 >>> def func(a): ... print('func_id:',id(a)) ... a = 2 ... print('after_func_id:',id(a),'id(2):',id(2)) ... >>> print('out_of_func_id:',id(a),'id(1):',id(1)) out_of_func_id: 501962480 id(1): 501962480 # 全局变量a的id >>> func(a) # 将全局参数a传入函数 func_id: 501962480 # a=1 的id after_func_id: 501962496 id(2): 501962496 >>> print(a) # 退出函数,a的值仍为1 1
当把全局a传递给函数后,函数自动复制一份引用。执行完a=2以后,id(a)的内存地址发生变化。可是跟外层的a没有关系。内存
>>> a = [] >>> def func2(a): ... print('func2_id:',id(a)) ... a.append(1) ... >>> print('out_of_func2_id',id(a)) out_of_func2_id 59694296 >>> func2(a) func2_id: 59694296 >>> print(a) [1]
变量a的类型为list,是可变对象。函数的引用指向的是可变对象,地址没有发生变化,因此函数操做后,a的内容发生了改变。
因此当再次操做func2(a)函数时,产生跟预期不同的结果:ci
>>> func2(a) func2_id: 59694296 # a地址不变 >>> print(a) [1, 1] # 由于第一次执行func2(a)时,已经修改了a=[1],再次调用时,在[1]里新增
def add_end( L=[] ): # 设置为一个list变量L(对象可变) L.append('end') return L >>> add_end( ) ['end'] >>> add_end() ['end', 'end']
当连续重复使用默认参数调用时,结果出现错误。
Python函数在定义的时候,默认参数L的值就被计算出来了,即[]。L也是一个变量,它指向对象[],每次调用该函数,若是改变了L的内容,则下次调用时,默认参数的内容就变了,再也不是函数定义时的[]了。
能够改成:
def add_end( L=None ): # L为不变对象 if L is None: L = [] L.append('end') return L
则不管调用多少次,都不会出现问题。
因此,定义默认参数要牢记一点:默认参数必须指向不变对象!由于不变对象一旦建立,对象内部的数据就不能修改,这样就减小了因为修改数据致使的错误。此外,因为对象不变,多任务环境下同时读取对象不须要加锁。
可变参数,即传入的参数个数是可变的,0至任意个。
由于参数个数不肯定,则可使用一个list 或者tuple传进来。以后在函数调用时会自动组装为一个tuple。
例如:
def calc(numbers): # 变量 sum = 0 for n in numbers: sum = sum + n * n return sum >>> calc( [1,2,3] ) # 传入的是一个list 14
利用可变参数 *args:
def calc( *numbers ): sum = 0 for n in numbers: # 在函数内部,numbers组装成一个tuple sum = sum + n * n return sum >>> calc( ) # 0个参数 0 >>> calc( 1,3,5,7 ) # 多个参数 84 >>> num = [1,2,3] # list >>> calc( *num ) # *list –> tuple 14 >>> t = (1,3,5) >>> calc( t ) # tuple(错误) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 4, in calc TypeError: can't multiply sequence by non-int of type 'tuple' >>> calc( *t ) 35
函数代码彻底不变。可是,调用该函数时,能够传入任意个参数,包括0个参数。
关键字参数**kw容许传入0个至任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。例如:
def person(name , age , **kw ): print('name:',name,'age:',age,'other:',kw) >>> person('xiong',18) name: xiong age: 18 other: {} >>> person('xiong',18,city = 'SH') # city是本来没有的参数,可是由于有**kw name: xiong age: 18 other: {'city': 'SH'}
关键参数有什么用?能够扩展函数的功能。好比在person()函数里面,能够保证接收到name和age这两个参数。可是若是提供更多参数,也能收到。固然也能够先组装一个dict,再把该dict转换为关键字参数传递进去:
>>> extra ={'city':'shanghai','job':'SET'} # dict的定义 >>> person('xiong',18,city = extra['city'],job=extra['job']) # dict的使用 name: xiong age: 18 other: {'city': 'shanghai', 'job': 'SET'} # dict的内容 >>> person('xiong',18,**extra) name: xiong age: 18 other: {'city': 'shanghai', 'job': 'SET'}
【总结】**extra表示把extra这个dict的全部key-value用关键字参数传入到函数的**kw参数,kw将得到一个dict,注意kw得到的dict是extra的一份拷贝,对kw的改动不会影响到函数外的extra。
若是要限制关键字参数的名字,就能够用命名关键字参数。须要一个特殊分隔符“”,“”后面的参数被视为命名关键字参数。若是缺乏“*”,Python解释器则没法识别位置参数和命名关键字参数。在调用时,必须指定参数名字与参数值。
例如,只接收city和job做为关键字参数,可使用以下定义:
def person( name ,age,*,city,job): print(name , age , city , job ) >>> person('xiong', 18, city='shanghai', job='tester') xiong 18 shanghai tester
若是函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就再也不须要一个特殊分隔符*了:
>>> def person( name,age,*args,city,job ): # 此处city和job也是命名关键字参数 ... print(name, age, city, job)
命名关键字参数必须传入参数名,若是没有传入参数名,调用将会报错:
>>> person('xlp',18,'shanghai','tester') # 错误调用 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: person() missing 2 required keyword-only arguments: 'city' and 'job' >>> person('xlp',18,city='shanghai',job='tester') # 正确调用 xlp 18 shanghai tester
命名关键字参数能够有缺省值,从而简化调用:
>>> def person1(name,age,*,city='shanghai',job): ... print(name,age,city,job) ... >>> person1('xlp',18,job='engineer') xlp 18 shanghai engineer
在Python中定义函数,能够用位置参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数均可以组合使用。
可是要注意,参数定义的顺序必须是:位置参数、默认参数、可变参数、命名关键字参数和关键字参数。
(1)定义可变参数和关键字参数的语法:
*args是可变参数,args接收的是一个list、tuple;
**kw是关键字参数,kw接收的是一个dict;
(2)调用函数时如何传入可变参数和关键字参数的语法:
可变参数直接传入:func(1,2,3)
可变参数间接传入:先组装成list或tuple,l=(1,2,3),再经过args传入,func(l)
关键字参数直接传入:func(a=1,b=2)
关键字参数间接传入:先组装成dict,d={‘a’:1,’b’:2},再经过kw传入,func(d)
(3)命名关键字参数 是为了限制调用者能够传入的参数名,同时能够提供默认值。
(4)定义命名的关键字参数在没有可变参数的状况下,不要忘记写分隔符*,不然定义的将是位置参数。
❤ thanks for watching, keep on updating...