Python 第3周 - Python基础-函数/作用域/递归/函数式编程/高阶函数
内容
- 函数的理解与使用
 - 作用域、局部变量与全局变量
 - 返回值
 - 递归
 - 函数式编程
 - 高阶函数与作业需求
 
函数的定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名
使用函数的好处:
1 简单语法定义: 2 def HaiWai(): #函数名 3 print ("chenchangqing") 4 5 HaiWai() #调用函数
2、传参数调用函数
1 #传统的写法 2 a = 10 3 b = 5 4 5 count = a * b 6 print ("A与B的积:",count) 7 8 #利用函数描述 9 def count(x,y): 10 count = x * y 11 print ("函数的表述:",count) 12 13 count(8,5) 14 15 #使用return进行访问,后面会讲return的使用 16 def test1(x,y): 17 test = x + y 18 return test 19 20 c = test1(9,5) 21 print (c)



1 def func(a,b=5,c=10): 2 print ("a is %d;B is %d;c IS %d"% (a,b,c)) 3 4 func(3) 5 func(a=4,b=5) 6 func(6,b=10,c=5) 7 func(b=1,c=3) 8 输出: 9 a is 3;B is 5;c IS 10 10 a is 4;B is 5;c IS 10 11 a is 6;B is 10;c IS 5 12 Traceback (most recent call last): 13 File "/Users/mac/PycharmProjects/untitled2/51CTO/3day/def1.py", line 41, in <module> 14 func(b=1,c=3) 15 TypeError: func() missing 1 required positional argument: 'a'
备注:func(b=1,c=3) 调用的时候,就报错误,TypeError: func() missing 1 required positional argument: 'a',找不到a值。调用函数的时候,首先先处理好排在前面的非默认参数的传参。
4、函数参数
函数中所用到的参数讲解:
- 形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量
 - 实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值
 
举例如下:

A、默认参数
1 def func(a,b,c): #a,b,c 为形式参数
2 print (a,b,c) 3 4 func(4,5,6) # 4,5,6 为实参 5
6
7 8 def func(a,b=5,c=10): # a 为形式参数,需要传入实际参数,来条调用函数,不然出错。b ,c 为默认参数。 9 print ("a is %d;B is %d;c IS %d"% (a,b,c)) 10 11 func(3) # 3 是给a 进行的传参,b,c 的位置则打印默认参数。 12 func(a=4,b=7) 13 func(6,b=10,c=5) 14 输出: 15 a: 3 b: 5 c: 10 16 a: 4 b: 7 c: 10 17 a: 6 b: 10 c: 5
总结:默认参数是可以在调用函数的时候进行更改:当没有给默认参数进行传参的时候,打印的则是默认的参数;当我们在调用函数时,重新给默认参数赋予一个新的值,则会打印新的值。注意:默认参数 一定是在放在形式参数的后面 ,如下:
- 错误:def test(a=10,b=5,c) 这个定义是要出错的
 - 正确:def test(c,a=10,b=5)
 
B、关键参数
正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可,但记住一个要求就是,关键参数必须放在位置参数之后。
1 def test(name,age,job): 2 print (name,age,job) 3 4 test("chen",18,"IT") #按顺序传参数 5 6 test(job="IT",age=22,name="chen") #把顺序捣乱,使用关键参数指定值传参。 7 输出: 8 chen 18 IT 9 chen 22 IT
C、非固定参数
当函数在定义时不确定用户想传入多少个参数,就可以使用非固定参数:
*args 的使用:会把多传入的参数变成一个元组形式打印
def test(name,age,*args):# *args 会把多传入的参数变成一个元组形式 print (name,age,args) test("chen",18)
输出:
chen 18 () #后面这个()就是args,只是因为没传值,所以为空
test("chen",22,"chenchangqing","IT") 输出:
chen 22 ('chenchangqing', 'IT') #在没有定义的部分,按照元组形式打印。
test(name="chen",age=22,name1="chenchangqing",JOB="IT") #不能按照关键参数进行传参,会报错。
输出:
  Traceback (most recent call last):
  File "/Users/mac/PycharmProjects/untitled2/51CTO/3day/def1.py", line 49, in <module>
    test(name="chen",age=22,name1="chenchangqing",JOB="IT")
TypeError: test() got an unexpected keyword argument 'name1'
**kwargs的使用:会把多传入的参数变成一个dict形式
1 def test(name,age,*args,**kwargs): #*kwargs 会把多传入的参数变成一个dict形式 2 print (name,age,args,kwargs) 3 4 test("chen",18) 5 输出: 6 chen 18 () {} #后面这个{}就是kwargs,只是因为没传值,所以为空 7 8 test("chen",22,"chenchangqing","IT") 9 输出: 10 chen 22 ('chenchangqing', 'IT') {} #后面这个{}就是kwargs,只是因为没传值,所以为空 11 12 test(name="chen",age=22,name1="chenchangqing",JOB="IT") 13 输出: 14 chen 22 () {'name1': 'chenchangqing', 'JOB': 'IT'}
备注:*args 不可以使用关键参数,**kwargs 可以使用关键参数以字典的形式打印。
作用域:函数体内设置的变量名,就为作用域。
name = "chechangqing"#脚本定义的最前面、开头,都统称为全局变量 def chen(qing): name = "changqing" #这个函数就是这个变量的作用域 print ("现在的名字:",name) chen("chen1203") #调用函数体,查看结果。调用了函数体内的变量参数 输出: 现在的名字: changqing print (name) 输出: chechangqing #调用了全局变量的参数
局部变量
举例:

全局变量
注意:一般情况下,不建议把局部变量变成全局变量,这样不利于排查。如果要使用全局变量,最后在编码的时候,在最前端进行设置。
局部变量例子说明:声明局部变量为全局变量,要用global进行声明。
1 A = "chenchangqing" #全局变量 2 def network(name,tel,gongzi,job="IT"): 3 global B #声明为全局变量 4 B = "chen123456789" #局部变量 5 print ("name:%s,age:%s Job:%s" % (name,tel,job)) 6 print ("Name is %s" % name) 7 print ("Tel is %s" % tel) 8 print ("Job is %s" % job) 9 print ("Gongzi is %s" % gongzi) 10 print ("A:",A) 11 print ("内部调用B:",B) 12 network("chenchangqing",15017591603,3000) 13 14 print ("外部调用B:",B) #如果没有做全局声明变量,外部调用会失败 15 输出: 16 name:chenchangqing,age:15017591603 Job:IT 17 Name is chenchangqing 18 Tel is 15017591603 19 Job is IT 20 Gongzi is 3000 21 A: chenchangqing 22 内部调用B: chen123456789 23 外部调用B: chen123456789
全局变量与局部变量的区别:
- 在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
 - 全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。
 - 当全局变量与局部变量同名时:这种情况可以把局部声明全局变量使用。但不建议把局部变量变成全局变量,这样不利于排查
 - 在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。
 
要获取到函数的执行结果,就可以用return语句把结果返回
备注:
- 函数在执行过程中只要遇到return语句,就会停止执行并返回结果,所以也可以理解为 return 语句代表着函数的结束
 - 如果未在函数中指定return,那这个函数的返回值为None
 
举例说明:
1 def math1(x,y): 2 if x > y: 3 return x + y 4 print ("This's ok!!!") #return 返回值,代表代码执行的结束。所以当x > y时,并不会执行 print的操作。程序已经结束运行。 5 elif x < y: 6 return x * y 7 else: 8 return x - y 9 10 A = int(input("Please your A number:")) 11 B = int(input("Please your B number:")) 12 source = math1(A,B) 13 print (source) 14 输出: 15 Please your A number:7 16 Please your B number:5 17 12
在函数内部、可以调用其他函数。如果一个函数在内部调用自身的本身,函数就叫递归函数。注意:递归函数要学会使用工具进行断点排查
递归特性:
- 必须有一个明确的结束条件。
 - 每次进入更深一层递归时,问题规模相比上次递归都应有所减少。
 - 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
 
1、使用递归,比较容易陷入死循环,如下:
1 def test(n): 2 if n > 0: 3 print (n) 4 test(n/2) 5 A = int(input("please input your number:")) 6 test(A)
进入了死循环,最大打印次数为999次。接下,就会直接报错
2、明确的结束条件,每次进入更深一层递归时,问题规模相比上次递归都应有所减少。
1 def test(n): 2 if n > 0: 3 print (n) 4 test(int(n/2)) #对上个函数例子中,重新输入的值取整数 5 A = int(input("please input your number:")) 6 test(A) 7 输出: 8 please input your number:10 9 10 10 5 11 2 12 1
3、利用递归函数,进行二分查找:
data_list = range(1,1000) #定义类列表 def search(find_number, data): mid = int(len(data)/2) print (data[mid]) #取整数,打印中间数值 if mid > 0: if find_number > data[mid]: #判断如果输入的数值大于中间数值,择取右边的数值列表 print ("Data is in right",mid,data[mid:]) search(find_number,data[mid:]) #把得到的值,重新输入給函数,进行循环调用 elif find_number < data[mid]:#判断如果输入的数值小于中间数值,择取左边的数值列表 print ("Data is in left",mid,data[:mid]) search(find_number, data[:mid]) else: print ("Find the number is: %s" % data[mid])#以上两种情况不存在,说明已经找到数值 elif data[0] == find_n: print ("Find the number is: %s " % data[0]) else: print ("sorry can not find number:%s",find_number) if __name__ == '__main__': #调用函数的程序入口,代码优先执行这一步 find_n = input("please input your number:").strip() if find_n.isdigit(): find_n = int(find_n) search(find_n,data_list) 运行输出如下: please input your number:235 -----中间值----- 500 Data is in left 499 range(1, 500) -----中间值----- 250 Data is in left 249 range(1, 250) -----中间值----- 125 Data is in right 124 range(125, 250) -----中间值----- 187 Data is in right 62 range(187, 250) -----中间值----- 218 Data is in right 31 range(218, 250) -----中间值----- 234 Data is in right 16 range(234, 250) -----中间值----- 242 Data is in left 8 range(234, 242) -----中间值----- 238 Data is in left 4 range(234, 238) -----中间值----- 236 Data is in left 2 range(234, 236) -----中间值----- 235 Find the number is: 235
函数编程的方法:
- 面向对象-类-class定义
 - 面向过程-过程-def定义
 - 函数式编程-函数-def定义
 
函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元。
函数式编程中的函数这个术语不是指计算机中的函数(实际上是Subroutine),而是指数学中的函数,即自变量的映射。也就是说一个函数的值仅决定于函数参数的值,不依赖其他状态。比如sqrt(x)函数计算x的平方根,只要x不变,不论什么时候调用,调用几次,值都是不变的。
Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。
变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
举例:
def test(): return 6 def test1(a,b): return a + b res1 = test1(3,test()) print (res1) 输出: 9 def test2(a,b,f): return f(a) + f(b) res2 = test2(3,-6,abs) #abs 表示是绝对值的函数 print (res2) 输出: 9
作业:
定义:员工消息表
根据员工信息表,实现增、删、改、查操作。
                    
                
                
            
        
浙公网安备 33010602011771号