python学习笔记day09 函数

函数:

函数的定义和函数的调用不是一回事,程序执行时,遇到定义函数,只会执行定义函数名处,里面的函数体这个时候是不会执行的;

只有到调用函数处才会执行里面的函数体;

返回值:

没有返回值: 无 return;   -----返回None

                       只有 return;----返回None

                       return None----返回None

有返回值:  可以返回任意数据类型;

                    返回多个值时,可以用多个变量接收,但是变量要对应,不多不少;或者只用一个变量接收也可以;

参数

定义函数处的参数为形参,形参可以包括位置参数和关键字参数(又称默认参数)且位置参数必须在关键字参数之前;

调用函数处的参数为实参,实参也包括位置参数和关键字参数,位置参数在前,关键字参数在后;

并且上述两种参数都可以只用位置参数,或者只使用关键字参数,当混用时需要满足位置参数在前的原则;

def func(a,b):  #形参仅使用位置参数;
    print(a+b)
func(1,2)   #实参采用位置参数,一一对应 a=1;b=2
func(1,b=2) #位置参数和关键字参数同时使用,位置参数在前;
func(b=1,a=2) #使用关键字参数,可以不按形参顺序赋值;
def func(a,b=2):  #形参同时使用位置参数和关键字参数,位置参数在前;
    print(a+b)

func(1,2)   #实参采用位置参数,一一对应 a=1;b=2
func(1,b=4) #位置参数和关键字参数同时使用,位置参数在前;
func(b=1,a=2) #使用关键字参数,可以不按形参顺序赋值;
def func(a=3,b=2):  #形参使用关键字参数;
    print(a+b)

func(1,2)   #实参采用位置参数,一一对应 a=1;b=2
func(1,b=4) #位置参数和关键字参数同时使用,位置参数在前;
func(b=1,a=2) #使用关键字参数,可以不按形参顺序赋值;

也就是不管定义时形参采取什么样的参数形式,调用时实参可以采用上述三种方式;

动态参数-- *args ----传入的值被当成tuple处理(按照位置参数)

定义时采用动态参数 *args 调用时可以传无数个参数,但是需要按照位置参数进行传递;

比如我们想计算很多个数的和,可能计算三个数,也可能计算100个数,,,

def func(*args):
    sum=0
    for i in args:
        sum+=i
    print(sum)
func(1,2,3,4)  #需按照位置参数进行传递
func(2,3,4,5,6,7,8)

动态参数*args 和位置参数,关键字参数放一起时的顺序:位置参数,*args ,关键字参数;

def func(a,*args,b=10):
    sum=0
    for i in args:
        sum+=i
    print(sum+a-b)
func(1,2,3,4,b=2)    # 传递进去时a被赋值为1,而2,3,4 传给了动态参数args,b的值采用关键字参数赋值为2
func(2,3,4,5,6,7,8)  # 传递进去时a被赋值为2,而3,4,5,6,7,8 传给了动态参数args,b的值采用默认值10

动态参数-- **kwargs-----传入的值当成字典处理(按照关键字参数)

def func(**kwargs):  #动态参数**kwargs,传入的值当成字典处理
    print(kwargs)
func(a=1,b=2,c=3)

当位置参数,动态参数*args,关键字参数,动态参数**kwargs同时存在时:

def func(a,*args,b=2,**kwargs): #位置参数,动态参数*args,关键字参数,动态参数**kwargs
    print(a)
    print(args)      #传入args的值被当成list;
    print(b)
    print(kwargs)  #传入**kwargs的值被当成字典

func(1,2,3,4,5,b=7,c=9,d=2)  # 1->a;   2,3,4,5-->args;     7---->b        c:2,d:9----> kwargs;
func(1,2,3,4,5,c=8,d=9)      # 1->a;   2,3,4,5-->args;     2(默认)(而不是前面的5)---->b        c:2,d:9----> kwargs;

运行结果:

顺序:位置参数,动态参数*agrs,关键字参数,动态参数**kwargs 

 调用函数处使用* 和**: 将tuple或者字典打散;(定义函数处再将其重新组合)

def func(*args):
    sum=0
    for i in args:
        sum+=i
    print(sum)
nums=[1,2,3,4,5]
func(nums[0],nums[1],nums[2],nums[3],nums[4])
func(*nums)

相当于调用函数处将nums列表的元素打散之后传给动态参数*args,定义函数处,将打散的数再重新组合乘一个tuple

再来看调用函数处使用** 将字典打散:

def func(**kwargs):
    print(kwargs)

dic={'a':1,'b':2,'c':3}
func(**dic)

如果定义函数处参数的值是一个可变数据类型,每次函数调用不传参数,则会一直共用这个可变数据类型的资源!!!

之前一直没搞懂的问题,现在终于懂了:

def func(L=[]):  #使用的默认参数的值是一个可变数据类型list
    L.append(1)
    print(L)
func()    #L=[1]
func([])  #L=[1]  #因为现在调用函数自己传了一个参数[] 不是原来的列表(已经在[]的基础上append了一个1)
func()    #L=[1,1] #使用的仍然是默认参数的值-->可变list 还是使用的原来那个list,也就是地址没变,但是list值变了,func()--->L=[1],还是,现在又增加了一个1--->[1,1]
fun()     #L=[1,1,1] 经过上面两个func()后默认参数还是指向原来的list,只不过这个list会变,不停的append

再举一个例子,仍然是定义函数处使用的默认参数的值为可变数据类型:

形参中的默认参数是可变数据类型,实参不传参,则始终操作的都是同一个数据类型(可变),所以默认参数这个可变数据类型的值是会发生改变的!!!

def func(k,dic={}):  # 位置参数k,关键字参数dic 是一个可变数据类型:字典
    dic[k]='value'
    print(dic)

func(1)  #传的位置参数1赋值给k 作为字典的键, 值为value--->dic={1:'value'}
func(2)  #字典仍使用默认参数,使用原来那个地址,但是这个字典不再是空的了,因为它会变化!--dic={1:'value',2:'value'}
func(3)  #dic={1:'value',2:'value'3,'value'}

talk is cheap,show me the code
原文地址:https://www.cnblogs.com/xuanxuanlove/p/9539025.html