DAY9 函数初识(各种参数的用法)
函数初始
为什么需要函数?
1.合并重复,减少代码的重复率。
2.测试方便
3.修改方便
4.打包
5.映射
函数的最主要目的:封装一个功能。
函数的定义:
def 函数名(argv): 函数体
def : 定义函数的关键字。
函数名:自定义函数名,一般都为小写字母,与变量名一样最好具有良好的描述性。
argv : 参数,可以有多个,用","逗号分隔
statement : 函数体,具体的代码
return :函数的返回值,默认不写的话返回的是None;可以没有返回值,可以返回一个值,可以返回多个值。
创建函数,调用函数:
def mylen(): """ 创建了一个名为mylen的函数 计算s1的长度 """ s1 = "hello world" length = 0 for i in s1: length = length+1 print(length) mylen() #执行函数,函数名()表示执行函数。
函数的返回值:return
作用:
1.函数一旦遇到return,就会结束。
2.给函数的执行者返回值,方便后续使用
类型:
1.没有返回值,默认返回的是None。
2.返回一个值。
3.返回多个值,以元组的形式返回。
'''没有返回值,默认返回的是None''' def mylen(): s1 = 'hello,world' length = 0 for i in s1: length = length +1 print(length) str_len = mylen() #因为没有设置返回值,所以默认返回None print(str_len) >>>None '''返回一个值''' def mylen(): s1 = 'hello,world' length = 0 for i in s1: length = length + 1 return length str_len = mylen() print(str_len) '''返回多个值:可以返回多个,任意数据类型的值''' def demo1(): return 1,2,3,4 def demo2(): return 1,['a','b'],3,4 res1 = demo1() res2 = demo2() print(res1) print(type(res1)) # 元组 print(res2) print(type(res2)) #元组
函数的参数:形参与实参
形参:函数完成其工作所需要的一项信息,只是一个形式,用于接受实参。
实参:调用函数时,实际传递给函数的信息。
'''站在实参的角度来看'''
1.位置参数
#位置参数:调用函数时,python必须将函数调用中的实参与每一个形参关联,为此最简单的关联就是按照位置关联。因此,位置参数中,形参与实参的个数必须一样,位置一一对应。 def describe_pet(animal_type,pet_name): print('I have a '+ animal_type + '.') print('My '+ animal_type +"'s name is " + pet_name.title()) describe_pet('dog','herry') >>> I have a dog. My dog's name is Herry #如果改变参数的位置 describe_pet('dog','herry') >>> I have a herry. #animal_type这个形参接受的就是‘herry’了. My herry's name is Dog
2.关键字参数
# 关键字参数:用在函数调用的时候,通过关键字传值,可以不需要一一对应位置顺序。 def mymax(x,y): the_max = x if x>y else y return the_max max_num = mymax(y=10,x=20) #位置不用一一对应了。 print(max_num)
3.混合型参数(位置参数+关键字参数)
# 位置参数与关键字参数混合调用,但是关键字参数必须在位置参数之后。 def mymax(x,y): the_max = x if x>y else y return the_max max_num = mymax(10,y=20) #关键字参数必须在位置参数之后 print(max_num)
'''站在形参的角度来看'''
1.位置参数,与上面的是一样的。
2.默认参数
''' 默认参数:把变化比较小的参数可以设置成一个默认值,在传参时可以忽略不传,如果不传就使用默认值;如果传,就会覆盖掉默认值。 默认参数使用场景:“参数的值不经常改变,但是一直在用” 谨记:默认参数的陷进!!!默认参数不要设置为可变数据类型。 ''' #默认参数 def stu_info(name,sex='male'): print(name,sex) stu_info('alex') #sex可以忽略不传 >>> alex,male stu_info('eva_j','female') #sex的默认值会被覆盖 >>> alex,female #默认参数的陷进:默认参数不要为可变数据类型。 def default_para(a,l=[]): l.append(a) print(l) default_para('alex') # >>>['alex'] default_para('egon') # >>>['alex', 'egon'] !!!通过查看id,发现两次调用函数列表的内存地址都是一样的,说明列表都是同一个列表!!!
#像列表这种可变类型的改进方法:
def default_para(a,L=None):
if L is None:
L = []
L.append(a)
return L
print(default_para('alex'))
>>>['alex']
print(default_para('egon'))
>>>['egon']
3.任意参数,动态参数:在函数定义的时候,在上*代表的是聚合。
一. *args:接受位置传值,把所有位置参数都由*args接受,聚合保存为一个元组。
#一。观察*args的表现形式 def foo(*args): return args,type(args) print(foo(1,2,3,4,5)) >>>((1, 2, 3, 4, 5), <class 'tuple'>) #所以可以观察到,*args会把接受到的位置参数组成一个元组。 #二。既然*args是一个元组的形式,那么就可以对它进行遍历。 def mysum(*args): the_sum = 0 for i in args: the_sum = the_sum + i return the_sum res = mysum(1,2,3,4) print(res) #三。观察位置参数,与*args接受参数 def foo2(a,b,c,*args): print(a) print(b) print(c) print(args) foo2(1,2,3,4,5,6,7,8) >>> 1 #根据位置参数,形参与实参一一对应,a接受了1 2 #根据位置参数,形参与实参一一对应,b接受了2 3 #根据位置参数,形参与实参一一对应,c接受了3 (4, 5, 6, 7, 8) #*args接受了剩下的所有位置参数;*args就相当于一个大胃王,把剩余的位置参数都吃掉。 #四。如果没有给*args传值,它会报错吗??? def foo3(a,b,c,*args): print(a) print(b) print(c) print(args) foo3(1,2,3) #根据形参与实参一一对应,a接受了1,b接受了2,c接受了3,*args没有参数,会如何? >>> 1 2 3 () #根据结果我们可以知道,就算没有给*args传值,它会形成一个()空元祖。 ''' 从上面的代码,我们可以知道。*args就是一个胃口极大的家伙,会把多个位置参数都接受。 所以位置参数必须放置在*args的前面。 '''
1.1 位置参数,默认参数,*args的顺序
#前提:从上面的代码,我们已经知道: #1.位置参数需要放在默认参数的前面。 #2.位置参数需要放在*args的前面。 #那么,默认参数和*args的排序位置又是怎么样的呢?我们接下来就来分析~ #一。默认参数在*args的前面 def foo4(a,b,c,d='alex',*args): print(a) print(b) print(c) print(d) print(args) foo4('he','bob','taibai','wusir','evj') >>> he #a接受'he' bob #b接受'bob' taibai #c接受'taibai' wusir #d原本是默认参数,这里接受到了新的值,所以原值被覆盖了 ('evj',) #*args接受剩下的位置参数 ##从上面看出,默认参数如果在*args的前面,原值就会被覆盖掉,所以默认参数需要放置到*args的后面##
参数顺序: ‘位置参数 *args 默认参数’
1.2 *args的拓展以及魔法方法
# 如果有现成的列表,可以通过“*列表名”把列表传入 #一。如果传入不加“*” l1 = [1,2,3] l2 = ['he','alex','wusir'] def func(*args): print(args) func(l1,l2) >>> ([1, 2, 3], ['he', 'alex', 'wusir']) #会把每个列表当成一个独立的元组的元素 #魔法方法:打散 l1 = [1,2,3] l2 = ['he','alex','wusir'] def func(*args): print(args) func(*l1,*l2) >>> (1, 2, 3, 'he', 'alex', 'wusir') #会把列表的元素打散,然后组成一个元组。
二. **kwargs:keyword args,顾名思义关键词动态参数,与字典对应。
# 一。**kwargs接受关键字参数,观察其表现形式 def func(**kwargs): print(kwargs,type(kwargs)) func(name='he',age=23,sex='male') >>> {'name': 'he', 'age': 23, 'sex': 'male'} <class 'dict'> #**kwargs接受多个关键词参数,将他们组织成一个字典的形式。 #二。所以**kwargs符合字典的所有特性。 def car(**kwargs): for k,v in kwargs.items(): print(f'{k}:{v}') car(color='red',price=20,user='he') >>> color:red price:20 user:he #三。从上面我们已经理清楚了位置参数,默认参数,*args的顺序的问题。现在,加入**kwargs会如何? ###系统规定了**kwargs放在所有参数的最后面。#### def func(a,b,*args,sex='male',**kwargs): print(a) print(b) print(args) print(sex) print(kwargs) func(1,2,3,4,5,6,name='he',age=23,sex='female') #所以,参数的位置为:位置参数,*args,默认参数,**kwargs
参数顺序: ‘位置参数 *args 默认参数 **kwargs’
2.1 **kwargs的拓展以及魔法方法
#如果现在有现成的列表,可以通过**dict把字典传入 dic = {'color':'red','price':100} def car(**kwargs): print(kwargs) car(**dic) >>> {'color': 'red', 'price': 100} # 魔术方法:打散 def func(**kwargs): print(kwargs) dic = {'name1':'he','age1':23} dic1 = {'name2':'alex','age2':33} func(**dic,**dic1) >>> {'name1': 'he', 'age1': 23, 'name2': 'alex', 'age2': 33}
三. 结合*args,**kwargs的函数,称为万能参数。
# *args接受所有的位置参数,**kwargs接受所哟关键字参数。 def func(*args,**kwargs); pass