11-Python-函数

1、函数的定义

定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可。其特性如下:

  • 减少重复代码
  • 使程序变的可扩展
  • 使程序变得易维护

2、语法定义

1 def func1():
2     '''test1'''  #声明函数的作用
3     print("test function1")
4     return 0  #返回值
5 
6 func1()  #调用函数
7 x = func1()  #将函数返回值赋值给x
8 print(x)

3、函数返回值

返回值个数=0,返回None
返回值个数=1,返回object
返回值个数>1,返回tuple

4、带有参数的函数

4.1、普通参数

函数的参数又分为形式参数实际参数

  • 形参变量:只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量。
  • 实际参数:可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值。
1 def func1(x,y):
2     print(x)
3     print(y)
4 
5 func1(1,2)  #位置参数,实参与形参一一对应,与位置有关
6 func1(y=2,x=1)  #关键字参数,与位置无关。但是需要注意的是:关键字参数必须在位置参数之后。
7 
8 func1(10,y=20) 
9 # func1(x=10,20)  这样写不行,因为关键字参数不能写在位置参数前面

 

4.2、默认参数

默认参数必须放在形参和*args的后面,**kwargs的前面。

 1 #现有代码如下:
 2 def stu_register(name,age,country,course):
 3     print("----注册学生信息------")
 4     print("姓名:",name)
 5     print("age:",age)
 6     print("国籍:",country)
 7     print("课程:",course)
 8  
 9 stu_register("王山炮",22,"CN","python_devops")
10 stu_register("张叫春",21,"CN","linux")
11 stu_register("刘老根",25,"CN","linux")
12 
13 #发现country都是相同的,因此可以给该参数一个默认值:
14 def stu_register(name,age,course,country='CN'):  #默认参数必须放形参的后面
15     print("----注册学生信息------")
16     print("姓名:",name)
17     print("age:",age)
18     print("国籍:",country)
19     print("课程:",course)
20  
21 stu_register("王山炮",22,"python_devops")
22 stu_register("张叫春",21,"linux")
23 stu_register("刘老根",25,"linux")

4.3、非固定参数

若你的函数在定义时不确定用户想传入多少个参数,就可以使用非固定参数。非固定参数必须放置形式参数之后,且*args放置在默认参数之前,**kwargs放置在*args和默认参数之后。 

 1 #*args:接收N个位置参数,转换成元组
 2 def stu_register(name,age,*args): # *args 会把多传入的参数变成一个元组形式,且*args必须放在形参之后,默认参数之前
 3     print(name,age,args)
 4    
 5 stu_register("Alex",22)  #Alex 22 () #输出:Alex 22 () #后面这个()就是args,只是因为没传值,所以为空元组
 6 
 7 stu_register("Jack",32,"CN","Python")  #输出:Jack 32 ('CN', 'Python')
 8 
 9 #注意默认参数的位置,只能放在*args之后
10 def stu_register(name,age,*args,sex="Male"): # *args 会把多传入的参数变成一个元组形式,且*args必须放在形参之后,默认参数之前
11     print(name,age,args,sex) 
12 
13 stu_register("Jack",32,"Python","CN")  --> Jack 32 ('Python','CN') Male
14 
15 #如果默认参数放在*args之前,那么会出现如下的情况:
16 def stu_register(name,age,sex="Male",*args):
17     print(name,age,sex,args)
18     
19 stu_register("Jack",32,"Python","CN")    -->  Jack 32 Python ('CN',)  # 位置参数Python传递的值会覆盖形式参数sex的默认值Male
20 # stu_register("Jack",32,sex="Male","Python","CN")这样又会报错,因为关键字参数不能出现在位置参数之前。
21 
22 #*args传递参数的方式
23 def func3(*args):
24     print(args)
25 
26 func3(1,2,3,4,5)
27 #如果传递列表或元组,想达到和如上一致的效果,那么就在列表或元组前加*
28 func3(*[1,2,3,4,5]) --> (1,2,3,4,5) # 站在实参的角度上,给序列(列表、元组)加上*,就是将这个序列按照顺序打散,传递给形参。站在形参的角度上,给变量加上*,就是按顺序组合所有传递过来的值。
29 func3(*(1,2,3,4,5)) --> (1,2,3,4,5)
30 #而如果直接传递列表或者元组,那么结果也是列表或元组
31 func3([1,2,3,4,5], )  -->  ([1, 2, 3, 4, 5],)
32 func3((1,2,3,4,5), )  -->  ((1, 2, 3, 4, 5),)
33 
34 
35 #**kwargs:接收N个关键字参数,转换成字典
36 
37 #**kwargs传递参数的方式
38 def func4(**kwargs):
39     print(kwargs)
40     
41 func4(a=1,b=2)  #和如下的传参方式等价
42 
43 d1 = {"a"=1, "b"=2}
44 func4(**d1)  # 如果想以字典的方式传递值,那么就要在字典前加上**。道理和*args传参方式一致
45 
46 #传递多种类型的参数
47 def stu_register(name,age,*args,sex="male",**kwargs): # **kwargs 会把多传入的参数变成一个字典形式,且**kwargs必须放在形参、*args和默认参数之后
48     print(name,age,args,sex,kwargs)
49   
50 stu_register("Alex",22)  #输出:Alex 22 () male {} #()是args,因为没传值,所以是空元组;后面这个{}就是kwargs,因为没传值,所以为空字典
51 
52 stu_register("Druid",32,"python",hobby="Female",province="ShanDong") #输出:Druid 32 ('python',) male {'hobby': 'Female', 'province': 'ShanDong'}

 

4.4、lambda表达式

 1 #普通函数
 2 def func1(x):
 3     return  x+100
 4 
 5 res = func1(100)
 6 
 7 #lambda表达式,等价于上面的函数
 8 func1 = lambda x:x+100
 9 
10 res = func1(111)
11 print(res)
12 
13 #lambda表达式之多参数
14 func2= lambda x,y:x+y+100
15 
16 res1 = func2(11,22)
17 print(res1)
18 
19 #lambda表达式之默认参数
20 func3 = lambda x,y=22:x+y+1001
21 res2 = func3(11)
22 print(res2)

4.5、递归

如果一个函数在内部调用自身本身,这个函数就是递归函数。

递归特性:

1. 必须有一个明确的结束条件。

2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少。

3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)。

堆栈扫盲http://www.cnblogs.com/lln7777/archive/2012/03/14/2396164.htm

1 def calc(num):
2     print(num)
3     if num//2 >= 1:  #结束的条件
4         return calc(num//2)
5 
6 calc(10)  #输出:10 5 2 1

5、高阶函数

变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数

1 def add(a,b,f):
2     return f(a)+f(b)
3 
4 res = add(-10,10,abs)  #将abs函数作为参数传递,然后在目标函数的内部用该函数进行计算
5 print(res)

6、闭包

   如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。

  

  当循环结束以后,循环体中的临时变量不会销毁,而是继续存在于执行环境中。且python的函数只有在执行时,才会去找函数体里的变量的值。

funclist = []  
for i in range(3):  
    def foo(x): print x + i  
    flist.append(foo)  
for f in funclist:  
    f(2)

#  --->输出结果为4 4 4。
原文地址:https://www.cnblogs.com/Druidchen/p/7755677.html