一、为什么要用函数,有什么特点
为防止代码的沉余,就是在程序中不断地重复出现的同样功能的代码块,先定义一个实现同样功能的代码块(函数),定义好后可以无限次的调用,显得更简洁方便,可读性更强。
s1 = "hello world" length = 0 for i in s1: length = length+1 print(length) s2 = "hello eva" length = 0 for i in s2: #重复上述的代码块功能 length = length+1 print(length)
二、函数的定义和调用
函数的定义:格式: def 函数名():固定的结构
1 def mylen(): 2 3 #函数的固定格式 def+函数名():先定义后使用,命名的规则和变量名一致, 4 # 不能用关键字,最好见名知意,只要定义一次就可以任意调用 5 6 s1='hello world' 7 length=0 8 for i in s1: 9 length=length+1 10 print(length) 11 # return length 12 # str_lne=mylen() 13 # print('str_lne:%s' %str_lne)
函数的结构:
def 函数名(参数1,参数2,*args,默认参数,**kwargs):
"""注释:函数功能和参数说明"""
函数体
……
return 返回值
定义:def 关键词开头,空格之后接函数名称和圆括号(),最后还有一个":"。
def 是固定的,不能变,空格 为了将def关键字和函数名分开
函数名:函数名只能包含字符串、下划线和数字且不能以数字开头。虽然函数名可以随便起,但我们给函数起名字还是要尽量简短,并能表达函数功能
注释:每一个函数都应该对功能和参数进行相应的说明,应该写在函数下面第一行。以增强代码的可读性。 # (""" """ ' ' '' '' )
调用:就是 函数名()
三、函数的返回值:
return关键字的作用
return 是一个关键字,在pycharm里,你会看到它变成蓝色了。你必须一字不差的把这个单词给背下来。
这个词翻译过来就是“返回”,所以我们管写在return后面的值叫“返回值”
要研究返回值,我们还要知道返回值有几种情况:分别是没有返回值、返回一个值、返回多个值
# 函数内要想返回给调用者值 必须用关键字return
"""
不写return
只写return
写return None
写return返回一个值
写return返回多个值
"""
没有返回值,不写return def mylen(): """计算s1的长度""" s1 = "hello world" length = 0 for i in s1: length = length+1 print(length) #函数的调用 str_len=mylen() #因为没有返回值,此时的str_len为None print('str_len : %s'%str_len)
二:返回一个值
def ret_demo(): print(111) return None print(2222) kil=ret_demo() print(kil) 返回的结果 >>2222 >>111 >>>None
关于赋值与调用的关系:首先a和b 被赋值指向同一个内存地址,后a又被重新赋值后指向了另一块内存地址,而b任然不变
三、返回多个值:定义好的函数,被调用后,return什么数据类型就返回什么类型的值,多种类型的话会以 '' 元组'' 的形式返回
1 def func(): 2 return(1,3,4,5,67,68,67,45,3,2,) 3 #可以return任何数据类型,多值被return的话默认以元组的形式返回, 4 res=func() 5 print(res) 6 def func1(): 7 return{'user_name':'Gilen','age':18,'habby':'write'} 8 def func2(): 9 return['day',12,'music','best','big',78] 10 print(func(),func1(),func2)
四、函数的参数:def mylen() #括号内的数就叫参数,分为形参和实参之分,在函数定义前命名的叫形参,调用过程命名的叫实参
#函数定义 def mylen(s1): """计算s1的长度""" length = 0 for i in s1: length = length+1 return length #函数调用 str_len = mylen("hello world") print('str_len : %s'%str_len)
实参与形参
参数还有分别:
我们调用函数时传递的这个“hello world”被称为实际参数,因为这个是实际的要交给函数的内容,简称实参。
定义函数时的s1,只是一个变量的名字,被称为形式参数,因为在定义函数的时候它只是一个形式,表示这里有一个参数,简称形参。
传递多个参数
参数可以传递多个,多个参数之间用逗号分割。def mylen(x, y)
1:位置参数: 在函数定义阶段按照位置从左往右依次书写的变量名 叫做函数位置形参
位置形参在调用的时候 必须为其传值
def my_max(x,y): print(x,y) if x > y: return x else: return y # res = my_max(1) # 在调用函数的时候 少一个实参不行 # res = my_max(1,2,3) # 在调用函数的时候 多一个实参也不行 # res = my_max(20,10) # 位置实参:在函数的调用阶段 传入的参数会按照位置一一对应给形参 # print(res)
第一种直接按照位置传 一一对应
2.按照关键字传值
# 第二种指名道姓的传 >>>:关键字传参 # my_max(y=20,x=10) # my_max(10,y=20) # 位置和关键字混合使用 # my_max(20,y=40) my_max(20,y=40,x=30)
3.位置、关键字形式混着用
注意:在函数的调用阶段 位置参数和关键字参数可以混合使用
但是必须保证
1.位置参数必须在关键字参数的前面(越短的越靠前,越长的越复杂的越靠后)
2.同一个形参不能被多次赋值
def mymax(x,y): #此时x = 10,y = 20 print(x,y) the_max = x if x > y else y return the_max #调用mymax不传递参数 ma = mymax() print(ma) #结果 TypeError: mymax() missing 2 required positional arguments: 'x' and 'y'
4、默认参数
默认值参数:在函数的定义阶段,形参(变量名)就已经被赋值了
在调用的时候可以不为默认值形参的传值,默认使用定义阶段就已经被绑定的值
在调用的时候如果可以给默认值形参传值,传了那么久使用你传的值
在定义阶段 默认值形参必须放在位置形参的后面 。
def my_max(x,y=100):
if x > y:
return x
return y res = my_max(200)
res1 = my_max(200,1000)
res2 = my_max(y=200,x=1000)
print(res2)
def register(username,age,gender='male'): print(username,age,gender) register('jason',18) register('tank',28) register('egon',84) register('kevin',58) ##默认的认为gender为’ male ‘ 如果不是的话在赋值修改即可 register('xiaohou',17,'female')
函数无论在什么地方被调用
都会跑到函数定义阶段去执行代码
形参中用到的值都是往函数定义阶段代码往上找
5、动态参数:
按位置传值多余的参数都由args统一接收,保存成一个元组的形式
形参中的*会将多余的(溢出的)位置实参 统一用元组的形式处理 传递给*后面的形参名
站在形参的角度 看 *
def func(x,y,*z): print(x,y,z) # z = (3, 4, 5, 6, 7, 8, 54, 43, 4, 5, 6, 6, 7, 8) func(1,2,3,4,5,6,7,8,54,43,4,5,6,6,7,8,)
x对应1,y对应2,溢出的部分赋值到z,且以元组的形式返回来
站在实参的角度 看 *
ef func(x,*z): print(x,z) func(1,*{1,2,3}) # *在形参中只能接收多余的位置实参 不能接收关键字实参 # *只能将列表 元组 集合 字符串 # *的内部你可以看成是for循环
站在形参的角度看 **
# **会接收所有多余的关键字参数 并将关键字参数 转换成字典的形式 字典的key就是关键字的名字
# 字典的value就是关键字的名字指向的值 将字典交给**后面的变量名
# 站在实参的角度看 **
def func(x,y,z): print(x,y,z) # func(12,3,4) # func(x=1,y=2,z=3) # d = {'x':1,'y':2,'z':333} # func(x=1,y=2,z=3) # func(**d) # 等价于func(x=1,y=2,z=333) # **会将字典拆封成 key = value的形式
总结 :* 与 **
*在形参中能够接受多余的位置参数 组织成一个 元祖 赋值给*后面的变量名
**在形参中能够接受多余的关键字参数 组织成一个 字典 赋值给**后面的变量名
*:在实参中 *能够将列表 元祖 集合 字符串 打散成位置 实参 的形式传递给函数
(*就看成是for循环取值)
**:在实参中 能将字典打散成 key=vlaue 的形式 按照关键字参数传递给函数
注意python推荐形参*和**通用的写法
def func2(*args,**kwargs):
print(args,kwargs)
func2(1,2,3,4,5,6,x=1,y=2,z = 3)