函数
函数就是具有某个具体功能的工具,函数可以帮助我们提高开发效率,避免代码过于繁琐,提高程序等的扩展性。
如何定义?
关键词:def
规则:函数名的命名规则与变量名一致,不能以关键字命名(*****),命名要做到见名知意。
# 函数在定义的时候只检测函数体的语法,不执行函数的代码。
***调用函数的固定格式:函数名()
# 函数名只要遇到括号就会立刻执行函数体代码;
# 代码中遇到函数名加括号,优先级最高;
# 先去执行函数,再看下面的代码。
函数包括有内置函数、自定义函数:
内置函数:python提前给你写好了的函数,直接调用就可以。如len()
自定义函数:必须先定义后调用****定义了的函数可以在任意位置调用。如:
l = [1,2,3,4,5] def my_len(): # 自定义函数 n = 0 for i in l: n += 1 print(n) # 5 res = my_len() print(res) # None # 由此可以看出,目前定义的函数有两个问题: 1.没有返回值,只能固定的执行打印操作 2.只能够固定的统计某一个容器类型的长度。
要想函数内返回给调用者值,必须用关键词return:
①不写return:函数默认返回None。如:
def func(): print('hahaha') # hahaha res = func() print(res) # None
②只写return:返回的也是None。如:
def func(): l = ['jason','egon','tank'] while True: for i in l: if i == 'egon': # break return # 当i为egon的时候 直接结束函数运行 print(i) # jason res = func() print(res) # None
ps:return除了可以返回值之外,还可以直接结束整个函数的运行。
③写return None:跟只写return是一样的。
④写return返回一个值:这个值可以是python任意类型数据。如:
def func(): return '123' def func1(): return [1,2,3] def func2(): return {'name':'jason'} def func3(): return (1,) def func4(): return {1,2,3,4,5} def func5(): return True print(func()) # 123 print(func1()) # [1, 2, 3] print(func2()) # {'name': 'jason'} print(func3()) # (1,) print(func4()) # {1, 2, 3, 4, 5} print(func5()) # True 可以看到,return返回的值可以是整型、列表、字典、元祖、集合、布尔值等各种python类型数据。
⑤写return返回多个值:return会自动将多个值一元祖的形式返回给调用者。如:
def func(): return 1,2,3,4 res = func() print(res) # 返回的是(1, 2, 3, 4) def func1(): return [1,2,3],[1,2,3],[1,2,3] res1 = func1() print(res1) # 返回的是([1, 2, 3], [1, 2, 3], [1, 2, 3]) def func2(): return {'name':'jason'},{'username':'tank'},{'user_name':'egon'} res2 = func2() print(res2) # 返回的是({'name': 'jason'}, {'username': 'tank'}, {'user_name': 'egon'}) # 不管你return的什么值,结果都以元祖的形式给你返回
如何不返回元祖?>>>自己手动加上你想返回的数据类型。如:
def func3(): return [[1,2,3,4],[1,2,3,4],[1,2,34]] # 想要返回的是列表类型 res3 = func3() print(res3) # 返回的是[[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 34]] 列表类型
小结:
1.所有的函数都有返回值,无论写不写return,不写的情况下默认为None。
2.只写return或return None并不是为了考虑返回值,而是为了结束函数的运行。
函数的参数:形参和实参
形参:函数的定义阶段,()内写的变量名是该函数的形式参数
实参:函数的调用阶段,()内实际传入的值叫做实际参数
关系:形参相当于变量名,实参相当于变量的值。(函数调用传参的过程,就是给形参变量名赋值的过程)
注意:形参与实参的绑定关系只在函数的调用阶段有效,函数运行结束后关系自动解除。此外,只在函数内部有效,函数外部无任何影响
因此现在可以总结出函数的简易结构:
def 函数名(形参1,形参2......) :
"""函数的注释,用来描述该函数的作用以及各个参数的类型"""
函数体代码1
函数体代码2
...
return 函数的返回值
如:
def func(x,y) : """ 该函数的作用 :param x:对形参x的解释 :param y:对形参y的解释 :return:对函数返回值的解释 """ print('ncegfbr') return 'ubvjhrsb'
此外,print(help(func))可以查看内置函数及自定义函数的注释。
位置参数:
位置形参:在函数定义阶段按照位置从左到右依次书写变量名,叫做函数的位置形参。(位置形参在调用的时候,必须为其传值)如:
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(1,2) # 结果为2,表明此时是一一对应关系,x对应1,y对应2
位置实参:在函数调用阶段,传入的参数会按照位置一一对应给形参。
ps:两种传参方式:
①直接按照位置以一对一,也就是上面的例子。
②指名道姓的传(关键字传参)
如:
def my_max(x,y): print(x,y) if x > y : return x else : return y res = my_max(x=1,y=2)
除此之外,还可以位置和关键字混合使用,如:
def my_max(x,y): print(x,y) if x > y : return x else : return y res = my_max(1,y=2)
但是,混合使用必须保证位置参数在关键字参数前面,且同一个形参不能被多次赋值。(越短越靠前,越长越复杂的越靠后)
默认值参数:(应用场景:当形参接收到的值比较单一的情况下)
在函数定义阶段,形参就已经被赋值了。
# 在调用的时候可以不为默认值形参传值,默认使用已经绑定的值;
# 在调用的时候如果可以给默认值形参传值,使用传后的值;
# 在定义阶段,默认值形参必须放啊在位置形参的后面。
如:
def register(username,age,gender='male'): # 已经被赋值的gender就是默认为male print(username,age,gender) register('jason',18) # jason 18 male register('tank',28) # tank 28 male register('egon',84) # egon 84 male register('kevin',58) # kevin 58 male register('xiaohou',17,'female') # xiaohou 17 female # 第三个参数不传则默认为male,传的话就为传的值,在此为female
*****************************
函数在定义阶段 内部所使用的变量都已经初始化完毕了
不会因为调用的位置的变化 而影响到内部的值(暂时可忽略)
函数无论在什么地方被调用
都会跑到函数定义阶段去执行代码
形参中用到的值都是往函数定义阶段代码往上找
**************************************
可变长参数:在形参和实参中用*和**表示不同的含义。
1.形参中*能够接收多余的位置参数,组织成一个元祖赋值给*后面的形参名。如:
def func(x,y,*z): print(x,y,z) func(1,2,3,4,5,6,7,8,54,43,4,5,6,6,7,8,) # 阴影部分为多余的未知参数 # 结果为1 2 (3, 4, 5, 6, 7, 8, 54, 43, 4, 5, 6, 6, 7, 8) # 其中z(*后面的形参名) = (3, 4, 5, 6, 7, 8, 54, 43, 4, 5, 6, 6, 7, 8) 元祖形式
2.形参中**能够接收多余的关键字参数,组织成一个字典赋值给**后面的形参名。如:
def func(x,y,**z): print(x,y,z) func(x=1,y=2,z=1,a=1,b=2,c=3) # 阴影部分为多余的关键字参数 # 结果为1 2 {'z': 1, 'a': 1, 'b': 2, 'c': 3} 其中z(**后面的形参名) = {'z': 1, 'a': 1, 'b': 2, 'c': 3}
组成的字典:字典的value就是关键字的名字指向的值
3.实参中*能够将列表、元祖、集合、字符串打散成位置实参的形式传递给函数。如:
def func(x,y,z): print(x,y,z) # func(*[1,2,3,4,5,6]) # *会将列表打散成位置实参一一传入等价于func(1,2,3,4,5,6) func(*(1,2,3)) # 1 2 3 等价于func(1,2,3) # *的内部你可以看成是for循环
4.在实参中**能够将字典打散成 key = value 的形式,按照关键字参数传送给函数。如:
def func(x,y,z): print(x,y,z) func(12,3,4) # 12 3 4 位置传参 func(x=1,y=2,z=3) # 1 2 3 关键字传参 d = {'x':1,'y':2,'z':333} func(**d) # 1 2 333 # 等价于func(x=1,y=2,z=333) **会将字典拆封成 key = value的形式
*********************************************************
attention:python中推荐使用形参*和**通用的写法:
def func(*args,**kwargs) :
print(args,kwargs)
func(?) # 里面可以是任意类型数据,但必须是先位置传参,后关键字传参。