阅读目录:
1、函数
2、函数定义,调用
3、函数参数
4、函数参数默认值
5、可变参数
6、函数参数
7、参数解构
内容:
1、函数
函数:
数学定义:y = f(x) ,y 是 x 的函数,x 是自变量。 y = f(x0,x1...,xn).
Python 函数:
-
-
- 由若干语句组成的语句块、函数名称、参数列表构成,他是组织代码的最小单元。
- 完成一定的功能
-
函数的作用:
-
-
- 结构化编程对代码的最基本的封装,一般按照功能组织一端代码。
- 封装的目的为了服用,减少冗余代码
- 代码更加简洁美观,可读易懂
-
函数的分类:
-
-
- 内建函数,如max()
- 库函数,如 math.ceil() 使用需要到入库 math
-
2、函数定义,调用
def 语句定义函数:
def 函数名(参数列表):
函数体(代码块)
[ return 返回值 ]
-
-
-
- 函数名就是标识符,命名要求一样
- 语句块必须缩进,约定4个空格
- Python的函数没有return 语句,隐式会返回一个None 值
- 定义中的参数列表成为形式参数,只是一种符号表达式,简称 形参
-
-
函数调用:
函数定义,只是声明了一个函数,它不会被执行,需要调用
调用方式:就是函数名加上小括号,括号内写上参数
条用时,写的参数是实际参数,是实实在在传入的值,简称 实参
函数举例
def add(x, y):
result = x + y
return result
out = add(4, 5)
print(out)
-
-
-
- 上面只是一个函数的定义,有一个函数叫做add,接受2 个参数
- 计算的结果,通过返回值返回
- 调用通过函数名 add加 2 个参数,返回值可使用变量接受
- 定义需要在调用前,也就是说调用时,已经被定义过,否则抛 NameError 异常
- 函数是可调用的对象,用 callable() ----callable(函数名)返回True 就是可悲调用的
- print() 本身是没有 返回值 return
-
- print(print(type(3)))
-
In [28]: print(print(type(3)))
<class 'int'>
None
-
- 先定义 后调用
-
-
3、函数参数
参数调用时 传入 的参数 要和定义的个数相匹配(可变参数例外)
***位置参数:
def f( x, y, z) 调用 f( 1, 2, 3)
按照参数定义顺序传入实参
***关键字参数:
def f( x, y, z) 调用使用 f( x=1, y=2, z=3)
使用形参的名字来出入实参的方式,如果使用了形参 名字,那么传参顺序就可和定义顺序 不同
传参:
f(z = None, y=10, z=[1] )
f((1,) , z=6,y = 4.2)
f(y=4,z=7, 2) : 错误的传参,位置参数,不能放在关键字参数之后
要求位置参数 必须放在关键字参数之前传入,位置参数是按照位置对应的
4、函数参数默认值:
参数默认值(缺省值)
定义时,在形参后跟上一个值
def add(x=4, y=5):
return x + y
1 def add(x=4, y=5): 2 return x + y 3 4 add(6,9) # 15 5 add(6, y=7) # 13 6 add(x=5) # 10 7 add() # 9 8 add(y=7) # 11 9 add(x=5, 6) # 语法错误 10 add(y=9, x=3)# 12 11 add(x=1, y=2)# 3
1 def add(x=4, y): # non-default argument follows default argument 2 return x + y 3 4 # add(6,9) # 15 5 # add(6, y=7) # 13 6 # add(x=5) # 10 7 # add() # 9 8 # add(y=7) # 11 9 # add(x=5, 6) # 语法错误 10 # add(y=9, x=3)# 12 11 # add(x=1, y=2)# 3
注: def add(x=4, y) 定义时错误的,缺省参数不能放在非缺省参数之前
作用:
参数的默认值可以在未传入足够的实参的时候,对没有给定 的参数赋值为默认值
参数非常多的时候,并不需要用户每次都输入所有的参数,简化函数调用
举例:
def login(host='localhost',username='jacke',password='ssss'): pass
5、可变参数
有多个数,需要累加求和
1 def add(nums): 2 sum = 0 3 for x in nums: 4 sum += x 5 return sum 6 7 add([1,2,3]) # 6 8 add((2,3,4))# 9
传入一个可迭代对象,迭代元素求和
可变参数:
一个形参可以匹配任意个参数
***位置参数的可变参数:
1 def add(*nums): 2 sum = 0 3 print(type(nums)) 4 for x in nums: 5 sum += x 6 print(sum) 7 8 add(3,4,6) 9 10 # <class 'tuple'> 11 # 13
注:
在形参前面使用* 表示该形参是可变参数,可以接受多个实参
收集多个实参为一个tuple
***关键字参数的可变参数: 只收集 关键字参数
1 def showconfig(**kwargs): 2 for k,v in kwargs.items(): 3 print(k,v) 4 print(kwargs) 5 kwargs['a'] = 0 6 print(kwargs) 7 showconfig(a=1, b=3, c=5) 8 9 # a 1 10 # b 3 11 # c 5 12 # {'a': 1, 'b': 3, 'c': 5} 13 # {'a': 0, 'b': 3, 'c': 5}
注:
形参前面使用** 符号,表示可以接受多个关键字参数
收集的实参名称和值 组成一个字典 ,这个字典可以修改
***可变参数混用:
配置信息打印
1 def showconfig(username, password, **kwargs): 2 3 def showconfig(username, *args, **kwargs): 4 5 def showconfig(username, password, **kwargs, *args): # 错误,可变关键字参数只能在可变位置参数之后
总结:
-
-
- 有位置可变参数和关键字参数可变参数
- 位置可变参数在形参前使用一个 星号 *
- 关键字可变参数在形参前使用两个星号**
- 位置可变参数和关键字可变参数都可以收集若干个实参,位置可变参数收集形成一个 元组,关键字可变参数收集形成一个 字典
- 混合使用参数的时候,可变参数要放到单数列表的最后,普通参数需要放在参数列表前面,位置可变参数需要在关键字可变参数之前
-
练习:
1 def fn(x, y, *args, **kwargs): 2 print(x) 3 print(y) 4 print(args) 5 print(kwargs) 6 7 # fn(3, 5, 7, 9, 10, a=1, b='python')# 正确 8 9 # # 因为之前位置参数已经给了,然后在给值就重复了 10 # fn(7, 9, x=1, a=1, b='python') # fn() got multiple values for argument 'x' 11 12 13 fn(2, a=1, b=2, y=1)# 正确
1 def fn(*args, x, y, **kwargs): 2 print(x) 3 print(y) 4 print(args) 5 print(kwargs) 6 7 fn(3,2,5) #keyword_only meiyou 给定 8 fn(3,5,a=1,b=3) #keyword_only meiyou 给定 9 fn(3,4,x=2,y=3,a=1) # 正确 10 11 # 2 12 # 3 13 # (3, 4) 14 # {'a': 1}
*** keyword-only 参数 (python 3 加入的)
如果 在一个 星号* 参数后,或者一个位置可变参数后,出现的普通参数,实际上已经不是普通参数了,而是keyword-only 参数
举例:只能通过关键字传参,要不就给缺省值
1 def fn(*args, x): 2 print(x) 3 print(args) 4 5 # fn(3,5) 6 # fn(3,4,5) 7 fn(3,4,x=2) 8 9 # 2 10 # (3, 4)
def fn( **kwargs, x): 直接报语法错误,可以理解为开挖如果是,会截获所有的关键字参数,就算写了 x=5, 也会被 可变关键字参数接受,所以x 永远得不到这个值。
def fn(*args, x, y=100):正确
keyword-only 参数的另一种形式:
1 def fn(*, x, y):# 逗号不能少!!!! 2 print(x, y) 3 4 fn(x=3, y=5)
注: * 之后,普通形参都变成了必须给出的keyword-only 参数
可变参数和参数默认值:
1 def fn(*args, x=5): 2 print(x) 3 print(args) 4 5 fn() # 等价fn(x=5) 6 fn(5) # 5 给了前者 7 # 5 8 # (5,) 9 fn(x=6) 10 # 6 11 # () 12 fn(1,2,3,x=10) 13 14 15 16 17 def fn(y ,*args, x=5): 18 pass 19 fn()# y没有 20 fn(y=17,2,3,x=1)# 位置参数要放在关键字参数之前 y=17,2,3 ----2,3,y=12 但是还是不对,因为y已经给了2,重复了
6、函数参数
参数规则:
参数列表参数 一般顺序是:普通参数,缺省参数,可变位置参数,keyword_only (可带缺省值),可变关键字参数。
def f(x, y, z=3, *arg, m=4,n,**kwargs):
pass
注意:
代码应该易读易懂,按照书写习惯定义函数参数
参数规则举例:
参数列表参数 一般顺序是:普通参数,缺省参数,可变位置参数,keyword_only (可带缺省值),可变关键字参数。
1 def connect(host='localhost', port='3306', user='admin',password='admin',**kwargs): 2 print(host, port) 3 print(user,password) 4 print(kwargs) 5 6 connect(db='cmdb') 7 connect(host='192.168.12.1', db='cmdb') 8 connect(host='192.168.12.1', db='cmdb', password='dasda') 9 ''' 10 localhost 3306 11 admin admin 12 {'db': 'cmdb'} 13 192.168.12.1 3306 14 admin admin 15 {'db': 'cmdb'} 16 192.168.12.1 3306 17 admin dasda 18 {'db': 'cmdb'} 19 '''
7、参数解构 :只能用在函数传参中,区别 普通的解构
1 def add(x, y): 2 return x + y 3 add(4,5) 4 add([4,5][1],(1,2)[1]) 5 add(*[4,5]) 6 add(*(4,5)) 7 add(*{4,5}) 8 add(*'45') 9 add(*range(100, 102))
1 def add(x, y): 2 return x + y 3 4 add(*{'a':1,'b':2}) #'ab' 5 # add(**{'a':1,'b':2}) # 报错 6 add(*{'x':1,'y':2}) #'xy' 7 add(**{'x':1,'y':2}) # 3
参数解构:
-
-
- 给函数提供实参的时候,可以在结合类型前 使用* 或者** ,把集合类型的结构 解开,提出所有的元素作为函数的实参。
- 非字典类型使用* 解构成位置参数
- 字典类型使用** 解构成关键字参数,不过要注意解构出来的 标识符 要一致
- 提取出来的元素数目要和参数的要求匹配,也要和参数的类型匹配
-
参数解构 和可变 参数
给函数提供实参的时候,可以再集合类型前使用* 或 **
1 def add(*iterable):# 注意,别犯傻,这个是 *args 2 print(iterable ) 3 result = 0 4 for x in iterable: 5 result += x 6 return result 7 8 # add(1,2,3) 9 10 # add(*[1,3,4]) 11 12 # add(*range(10 )) 13 14 add(range(10)) # 报错,将range(10)给了 iterable这个元组 (range(0, 10),) 15 # 虽然这个元组可迭代,但是就一个元素,x + 0 是什么鬼?