五、 函数

1.函数基础

1)定义函数

定义函数的格式如下:

def 函数名():
    代码

示例:

# 定义一个函数,能够完成打印信息的功能
def printInfo():
    print('------------------------------------')
    print('         人生苦短,我用Python')
    print('------------------------------------')
2)调用函数

定义了函数之后,就相当于有了一个具有某些功能的代码,想要让这些代码能够执行,需要调用它

调用函数很简单的,通过**函数名()**即可完成调用

# 定义完函数后,函数是不会自动执行的,需要调用它才可以
printInfo()

注意:

  • 每次调用函数时,函数都会从头开始执行,当这个函数中的代码执行完毕后,意味着调用结束了
  • 当然了如果函数中执行到了return也会结束函数
3)函数参数(一)
# 定义带有参数的函数
def add2num(a, b):
    c = a + b
    print(c)


# 调用带有参数的函数
add2num(11, 22)
# 调用带有参数的函数时,需要在小括号中,传递数据
4)调用函数时参数的顺序
def test(a,b):
    print(a,b)

test(1,2)

test(b=1,a=2)

 #test(b=1,2) 错误 
5)函数返回值(一)

程序中函数完成一件事情后,最后给调用者的结果。

想要在函数中把结果返回给调用者,需要在函数中使用return

#带有返回值的函数
def add2num(a, b):
    c = a+b
    return c

如果一个函数返回了一个数据,那么想要用这个数据,那么就需要保存

#保存函数的返回值
#定义函数
def add2num(a, b):
    return a+b

#调用函数,顺便保存函数的返回值
result = add2num(100,98)

#因为result已经保存了add2num的返回值,所以接下来就可以使用了
print(result)
6)函数的文档说明

语法:

def 函数名(参数):
    """ 说明文档的位置 """
    代码
    ......
  • 查看函数的说明文档
# help(len)  # help函数作用:查看函数的说明文档(函数的解释说明的信息)

# 函数的说明文档的高级使用
def sum_num1(a, b):
    """
    求和函数sum_num1
    :param a: 参数1
    :param b: 参数2
    :return: 返回值
    """
    return a + b
help(sum_num1)


7)函数的嵌套调用
def testB():
    print('---- testB start----')
    print('这里是testB函数执行的代码...(省略)...')
    print('---- testB end----')

def testA():
    print('---- testA start----')
    testB()
    print('---- testA end----')

testA()

总结:

  • 一个函数里面又调用了另外一个函数,这就是所谓的函数嵌套调用
  • 如果函数A中,调用了另外一个函数B,那么先把函数B中的任务都执行完毕之后才会回到上次 函数A执行的位置
8)局部变量
  • 局部变量,就是在函数内部定义的变量
  • 其作用范围是这个函数内部,即只能在这个函数中使用,在函数的外部是不能使用的
  • 因为其作用范围只是在自己的函数内部,所以不同的函数可以定义相同名字的局部变量(打个比方,把你、我是当做成函数,把局部变量理解为每个人手里的手机,你可有个iPhone8,我当然也可以有个iPhone8了, 互不相关)
  • 局部变量的作用,为了临时保存数据需要在函数中定义变量来进行存储
  • 当函数调用时,局部变量被创建,当函数调用完成后这个变量就不能够使用了
9)全局变量

如果一个变量,既能在一个函数中使用,也能在其他的函数中使用,这样的变量就是全局变量

demo如下:

# 定义全局变量
a = 100

def test1():
    print(a)  # 虽然没有定义变量a但是依然可以获取其数据

def test2():
    print(a)  # 虽然没有定义变量a但是依然可以获取其数据

# 调用函数
test1()
test2()

总结:

  • 在函数外边定义的变量叫做全局变量
  • 全局变量能够在所有的函数中进行访问
10)全局变量和局部变量名字相同问题
# B函数想要a的取值是200
a = 100

print(a)

def testA():
    print(a)

def testB():
    # a = 200  # 如果直接修改a=200,此时的a是全局a还是局部a? -- 得到结论:这个a是局部变量
    # # 因为在全局位置(B函数调用后)打印a得到的不是200而是100
    # print(a)

    # 想要修改全局变量a,值是200
    global a  # 声明a为全局变量
    a = 200
    print(a)

testA()
testB()

print(a)

"""
总结:
    1. 如果在函数里面直接把变量a=200赋值,此时的a不是全局变量的修改,而是相当于在函数内部声明了一个新的局部变量
    2. 函数体内部修改全局变量: 先global声明a为全局变量,然后再变量重新赋值
"""

总结:

  • 当函数内出现局部变量和全局变量相同名字时,函数内部中的 变量名 = 数据 此时理解为定义了一个局部变量,而不是修改全局变量的值
  • 如果在函数中出现global 全局变量的名字 那么这个函数中即使出现和全局变量名相同的变量名 = 数据 也理解为对全局变量进行修改,而不是定义局部变量
  • 如果在一个函数中需要对多个全局变量进行修改,那么可以使用
# 可以使用一次global对多个全局变量进行声明
global a, b
# 还可以用多次global声明都是可以的
# global a
# global b
11)多函数程序的基本使用流程

一般在实际开发过程中,一个程序往往由多个函数(后面知识中会讲解类)组成,并且多个函数共享某些数据,因此下面来总结下,多个函数中共享数据的几种方式

  1. 使用全局变量
g_num = 0

def test1():
    global g_num
    # 将处理结果存储到全局变量g_num中.....
    g_num = 100

def test2():
    # 通过获取全局变量g_num的值, 从而获取test1函数处理之后的结果
    print(g_num)

# 1. 先调用test1得到数据并且存到全局变量中
test1()

# 2. 再调用test2,处理test1函数执行之后的这个值
test2()
  1. 使用函数的返回值、参数
def test1():
     # 通过return将一个数据结果返回
     return 50

def test2(num):
    # 通过形参的方式保存传递过来的数据,就可以处理了
    print(num)

# 1. 先调用test1得到数据并且存到变量result中
result = test1()

# 2. 调用test2时,将result的值传递到test2中,从而让这个函数对其进行处理
test2(result)

3.函数嵌套调用

def test1():
    # 通过return将一个数据结果返回
    return 20

def test2():
    # 1. 先调用test1并且把结果返回来
    result = test1()
    # 2. 对result进行处理
    print(result)

# 调用test2时,完成所有的处理
test2()
12)函数返回值(二)
  • 一个函数中可以有多个return语句,但是只要有一个return语句被执行到,那么这个函数就会结束了,因此后面的return没有什么用处

  • 不同的场景下执行不同的return,代码如下

      def create_nums(num):
          print("---1---")
          if num == 100:
              print("---2---")
              return num+1  # 函数中下面的代码不会被执行,因为return除了能够将数据返回之外,还有一个隐藏的功能:结束函数
          else:
              print("---3---")
              return num+2
          print("---4---")
    
      result1 = create_nums(100)
      print(result1)  # 打印101
      result2 = create_nums(200)
      print(result2)  # 打印202
    

    一个函数返回多个数据的方式

def divid(a, b):
    shang = a//b
    yushu = a%b 
    return shang, yushu  #默认是元组

result = divid(5, 2)
print(result)  # 输出(2, 1)

总结:

  • return后面可以是元组,列表、字典等,只要是能够存储多个数据的类型,就可以一次性返回多个数据

          def function():
              # return [1, 2, 3]
              # return (1, 2, 3)
              return {"num1": 1, "num2": 2, "num3": 3}
    
  • 如果return后面有多个数据,那么默认是元组

          In [1]: a = 1, 2
          In [2]: a
          Out[2]: (1, 2)
    
          In [3]:
          In [3]: b = (1, 2)
          In [4]: b
          Out[4]: (1, 2)
    
          In [5]:
    
13)函数参数(二)

位置参数:调用函数时根据函数定义的参数位置来传递参数。

def user_info(name, age, gender):
    print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')


user_info('TOM', 20, '男')

传递和定义参数的顺序及个数必须一致

关键字参数:函数调用,通过“键=值”形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求。

def user_info(name, age, gender):
    print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')


user_info('Rose', age=20, gender='女')
user_info('小明', gender='男', age=16)

函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序。

缺省参数:调用函数时,缺省参数的值如果没有传入,则取默认值。

#下例会打印默认的age,如果age没有被传入:
def printinfo(name, age=35):
   # 打印任何传入的字符串
   print("name: %s" % name)
   print("age %d" % age)

# 调用printinfo函数
printinfo(name="miki")  # 在函数执行过程中 age去默认值35
printinfo(age=9 ,name="miki")

总结:

  • 在形参中默认有值的参数,称之为缺省参数

  • 带有默认值的参数一定要位于参数列表的最后面

    #下面函数定义是错误的
    def printinfo(name, age=35, sex):
         print name
     
    

不定长参数:有时可能需要一个函数能处理比当初声明时更多的参数, 这些参数叫做不定长参数,声明时不会命名。

基本语法如下:

def functionname([formal_args,] *args, **kwargs):
   """函数_文档字符串"""
   function_suite
   return [expression]

注意:

  • 加了星号(*)的变量args会存放所有未命名的变量参数,args为元组
  • 而加**的变量kwargs会存放命名参数,即形如key=value的参数, kwargs为字典.

所有位置参数

# 接收所有位置参数,返回一个元组
def user_info(*args342df):
    print(args342df)


user_info('TOM')
user_info('TOM', 20)
user_info('TOM', 20, 'man')
user_info()

所有关键字参数

# 收集所有关键字参数,返回一个字典
def user_info(**kwargs):
    print(kwargs)


user_info()
user_info(name='TOM')
user_info(name='TOM', age=20)

缺省参数,所有关键字参数,所有位置参数

# 缺省参数在*args后面
def sum_nums_3(a, *args, b=22, c=33, **kwargs):
    print(a)
    print(b)
    print(c)
    print(args)
    print(kwargs)

sum_nums_3(100, 200, 300, 400, 500, 600, 700, b=1, c=2, mm=800, nn=900)

总结:

  • 如果很多个值都是不定长参数,那么这种情况下,可以将缺省参数放到 *args的后面, 但如果有**kwargs的话,**kwargs必须是最后的
14)拆包

对返回的数据直接拆包,本质是对元组拆包

def get_my_info():
    high = 178
    weight = 100
    age = 18
    return high, weight, age


# result = get_my_info()
# print(result)

my_high, my_weight, my_age = get_my_info()
print(my_high)
print(my_weight)
print(my_age)

总结:
拆包时要注意,需要拆的数据的个数要与变量的个数相同,否则程序会异常
除了对元组拆包之外,还可以对列表、字典等拆包

#字典数据拆包: 变量存储的数据是key值
# 先准备字典,然后拆包
dict1 = {'name': 'TOM', 'age': 20}
# dict1中有两个键值对,拆包的时候用两个变量接收数据
a, b = dict1
print(a)
print(b)

# v值
print(dict1[a])
print(dict1[b])

15)交换2个变量的值
a, b = 1, 2
print(a)
print(b)


a, b = b, a
print(a)
print(b)

16)传递元组和字典给可变参数

传递元组给可变参数args

在实参的前面加上*的作用是将元组中的元素解包成一个一个的元素传递给函数. 对于元组 列表以及集合都可以使用

def func(*args):
    for ele in args:
        print(ele)

l = [1,2,3]
# 传递元组给可变参数
func(*l)

传递字典给可变参数kwargs

在实参的前面加上**的作用是将元组中的元素解包成一个一个的不存在的关键字参数传递给函数.

如果字典前面加上*表示的是将字典的key值解包出来

def func(**kwargs):
    for key,value in kwargs.items():
        print(key,value)

# 调用
d = {'name':'张三','age':30}
func(**d)
17) 自定义函数注意事项
  • 一个函数到底有没有返回值,就看有没有return,因为只有return才可以返回数据
  • 在开发中往往根据需求来设计函数需不需要返回值
  • 函数中,可以有多个return语句,但是只要执行到一个return语句,那么就意味着这个函数的调用完成
  • 不仅要避免函数名之间不能相同,还要避免 变量名和函数名相同的,否则都会出现问题

2.引用

引用就是变量指向数据存储空间的现象 使用id(数据/变量)操作获取数据存储的内存空间引用地址

在python中,值是靠引用来传递来的。

可以用id()来判断两个变量是否为同一个值的引用。 我们可以将id值理解为那块内存的地址标示。

1)不可变类型

地址存储的内容不可变

a = 1
b = a

print(b)

# 发现a和b的id值相同的
print(id(a))
print(id(b))

# 修改a的数据测试id值
a = 2

print(b)

# 因为修改了a的数据,内存要开辟另外一份内存取存储2,id检测a和b的地址不同
print(id(a))
print(id(b))



2)可变类型

地址存储的内容 可以改变

#  可变类型:列表
aa = [10, 20]
bb = aa

print(bb)

print(id(aa))
print(id(bb))

aa.append(30)
print(aa)
print(bb)  # 列表是可变类型

print(id(aa))
print(id(bb))#输出地址相同

总结:

  • 之前为了更好的理解变量,可以把a=100理解为变量a中存放了100,事实上变量a存储是100的引用(可理解为在内存中的一个编号)
3)引用当做实参
def test1(b):  # 变量b一定是一个局部变量,就看它指向的是谁?可变还是不可变
    b += b  # += 是直接对b指向的空间进行修改,而不是让b指向一个新的
    # b = b+b  # xx = xx+yyy 先把=号右边的结果计算出来,然后让b指向这个新的地方,不管原来b指向谁
                # 现在b一定指向这个新的地方

# a = [11, 22]
a = 100
test1(a)
print(a)

总结:

  • Python中函数参数是引用传递(注意不是值传递)
  • 对于不可变类型,因变量不能修改,所以运算不会影响到变量自身
  • 而对于可变类型来说,函数体中的运算有可能会更改传入的参数变量
4)实现str.split()方法的替换
def mySplit(msg,splitStr):
    '''
    切割字符串  返回列表
    :param msg:
    :return:
    '''
    # 1.定义列表保存结果
    result = []
    # 定义变量保存右边的字符串
    rightStr = msg[:]
    # 2.获取第一个出现的分隔字符串
    index = rightStr.find(splitStr)
    while index!=-1:
        # 3.把这个分隔的字符串前面的部分添加到结果列表中
        # 获取前面部分
        leftStr = rightStr[:index]
        if leftStr:
            # 添加到列表中
            result.append(leftStr)
        # 修改右边的字符串
        rightStr = rightStr[index+len(splitStr):]
        # 继续查找索引
        index = rightStr.find(splitStr)
    if rightStr:
        # 添加最后一部分内容
        result.append(rightStr)
    # 返回结果
    return result

print(mySplit('hellohellohdf','o'))
5)可变、不可变类型分类

所谓可变类型与不可变类型指:数据能够直接进⾏修改,如果能直接修改那么就是可变,否则是不可变.

可变类型

  • 列表
  • 字典
  • 集合

不可变类型

  • 整型
  • 浮点型
  • 字符串
  • 元组

3. 函数应用:学生管理系统

1)系统简介

需求:进⼊系统显示系统功能界⾯,功能如下:

  1. 添加学员
  2. 删除学员
  3. 修改学员信息
  4. 查询学员信息
  5. 显示所有学员信息
  6. 退出系统

系统共6个功能,⽤户根据⾃⼰需求选取。

2)步骤分析
  1. 显示功能界⾯

  2. ⽤户输⼊功能序号

  3. 根据⽤户输⼊的功能序号,执⾏不同的功能(函数)

    3.1 定义函数

    3.2 调⽤函数

3) 显示功能界⾯

定义函数 print_info ,负责显示系统功能。

def print_info():
 print('-' * 20)
 print('欢迎登录学员管理系统')
 print('1: 添加学员')
 print('2: 删除学员')
 print('3: 修改学员信息')
 print('4: 查询学员信息')
 print('5: 显示所有学员信息')
 print('6: 退出系统')
 print('-' * 20)


print_info()
4)⽤户输⼊序号,选择功能
user_num = input('请选择您需要的功能序号:') 1
5)根据⽤户选择,执⾏不同的功能
if user_num == '1':
    print('添加学员')
elif user_num == '2':
    print('删除学员')
elif user_num == '3':
    print('修改学员信息')
elif user_num == '4':
    print('查询学员信息')
elif user_num == '5':
    print('显示所有学员信息')
elif user_num == '6':
    pr
    int('退出系统')
#如果⽤户输⼊1-6以外的数字,需要提示⽤户。
while True:
    # 1. 显示功能界⾯
    print_info()

    # 2. ⽤户选择功能
    user_num = input('请选择您需要的功能序号:')
    # 3. 根据⽤户选择,执⾏不同的功能
    if user_num == '1':
        print('添加学员')
    elif user_num == '2':
        print('删除学员')
    elif user_num == '3':
        print('修改学员信息')
    elif user_num == '4':
        print('查询学员信息')
    elif user_num == '5':
        print('显示所有学员信息')
    elif user_num == '6':
        print('退出系统')
    else:
        print('输⼊错误,请重新输⼊!!!')
6)定义不同功能的函数

所有功能函数都是操作学员信息,存储所有学员信息应该是⼀个全局变量,数据类型为列表。

info = []
'''
 添加学员

- 需求分析

- 接收⽤户输⼊学员信息,并保存

- 判断是否添加学员信息

  2.1 如果学员姓名已经存在,则报错提示

  2.2 如果学员姓名不存在,则准备空字典,将⽤户输⼊的数据追加到字典,再列表追加字典数据

- 对应的if条件成⽴的位置调⽤该函数

- 代码实现
'''
def add_info():
    """ 添加学员 """
    # 接收⽤户输⼊学员信息
    new_id = input('请输⼊学号:')
    new_name = input('请输⼊姓名:')
    new_tel = input('请输⼊⼿机号:')

    # 声明info是全局变量
    global info
    # 检测⽤户输⼊的姓名是否存在,存在则报错提示
    for i in info:
        if new_name == i['name']:
            print('该⽤户已经存在!')
            return
        # 如果⽤户输⼊的姓名不存在,则添加该学员信息
        info_dict = {}

        # 将⽤户输⼊的数据追加到字典
        info_dict['id'] = new_id
        info_dict['name'] = new_name
        info_dict['tel'] = new_tel

        # 将这个学员的字典数据追加到列表
        info.append(info_dict)

        print(info)
''' 删除学员
按⽤户输⼊的学员姓名进⾏删除

1. ⽤户输⼊⽬标学员姓名

2. 检查这个学员是否存在

   2.1 如果存在,则列表删除这个数据

   2.2 如果不存在,则提示“该⽤户不存在”

3. 对应的if条件成⽴的位置调⽤该函数

'''
def del_info():
    """删除学员"""
    # 1. ⽤户输⼊要删除的学员的姓名
    del_name = input('请输⼊要删除的学员的姓名:')
    global info
    # 2. 判断学员是否存在:如果输⼊的姓名存在则删除,否则报错提示
    for i in info:
        if del_name == i['name']:
            info.remove(i)
            break
    else:
        print('该学员不存在')
    print(info)
# 修改函数
'''- 需求分析

- ⽤户输⼊⽬标学员姓名

- 检查这个学员是否存在

  2.1 如果存在,则修改这位学员的信息,例如⼿机号

  2.2 如果不存在,则报错

- 对应的if条件成⽴的位置调⽤该函数

- 代码实现'''
def modify_info():
    """修改函数"""
    # 1. ⽤户输⼊要修改的学员的姓名
    modify_name = input('请输⼊要修改的学员的姓名:')
    global info
    # 2. 判断学员是否存在:如果输⼊的姓名存在则修改⼿机号,否则报错提示
    for i in info:
        if modify_name == i['name']:
            i['tel'] = input('请输⼊新的⼿机号:')
            break
    else:
        print('该学员不存在')

    print(info)
# 查询学员
'''- 需求分析

- ⽤户输⼊⽬标学员姓名

- 检查学员是否存在

  2.1 如果存在,则显示这个学员的信息

  2.2 如果不存在,则报错提示

- 对应的if条件成⽴的位置调⽤该函数

'''
def search_info():
    """查询学员"""
    # 1. 输⼊要查找的学员姓名:
    search_name = input('请输⼊要查找的学员姓名:')
    global info
    # 2. 判断学员是否存在:如果输⼊的姓名存在则显示这位学员信息,否则报错提示
    for i in info:
        if search_name == i['name']:
            print('查找到的学员信息如下:----------')
            print(f"该学员的学号是{i['id']}, 姓名是{i['name']}, ⼿机号是{i['tel']}")
            break
        else:
            print('该学员不存在')
# 显示所有学员信息
def print_all():
    """ 显示所有学员信息 """
    print('学号\t姓名\t⼿机号')
    for i in info:
        print(f'{i["id"]}\t{i["name"]}\t{i["tel"]}')
#在⽤户输⼊功能序号 6 的时候要退出系统 
elif user_num == '6':
    exit_flag = input('确定要退出吗?yes or no')
    if exit_flag == 'yes':
        break
7)完整代码
import time
import os

# 定一个列表,用来存储所有的学生信息(每个学生是一个字典)
info_list = []


def print_menu():
    print("---------------------------")
    print("      学生管理系统 V1.0")
    print(" 1:添加学生")
    print(" 2:删除学生")
    print(" 3:修改学生")
    print(" 4:查询学生")
    print(" 5:显示所有学生")
    print(" 6:退出系统")
    print("---------------------------")


def add_new_info():
    """添加学生信息"""
    global info_list

    new_name = input("请输入姓名:")
    new_tel = input("请输入手机号:")
    new_qq = input("请输入QQ:")

    for temp_info in info_list:
        if temp_info['name'] == new_name:
            print("此用户名已经被占用,请重新输入")
            return  # 如果一个函数只有return就相当于让函数结束,没有返回值

    # 定义一个字典,用来存储用户的学生信息(这是一个字典)
    info = {}

    # 向字典中添加数据
    info["name"] = new_name
    info["tel"] = new_tel
    info["qq"] = new_qq

    # 向列表中添加这个字典
    info_list.append(info)


def del_info():
    """删除学生信息"""
    global info_list

    del_num = int(input("请输入要删除的序号:"))
    if 0 <= del_num < len(info_list):
        del_flag = input("你确定要删除么?yes or no")
        if del_flag == "yes":
            del info_list[del_num]
    else:
        print("输入序号有误,请重新输入")


def modify_info():
    """修改学生信息"""
    global info_list

    modify_num = int(input("请输入要修改的序号:"))
    if 0 <= modify_num < len(info_list):
        print("你要修改的信息是:")
        print("name:%s, tel:%s, QQ:%s" % (info_list[modify_num]['name'],
            info_list[modify_num]['tel'],info_list[modify_num]['qq']))
        info_list[modify_num]['name'] = input("请输入新的姓名:")
        info_list[modify_num]['tel'] = input("请输入新的手机号:")
        info_list[modify_num]['qq'] = input("请输入新QQ:")
    else:
        print("输入序号有误,请重新输入")


def search_info():
    """查询学生信息"""
    search_name = input("请输入要查询的学生姓名:")
    for temp_info in info_list:
        if temp_info['name'] == search_name:
            print("查询到的信息如下:")
            print("name:%s, tel:%s, QQ:%s" % (temp_info['name'],
                temp_info['tel'], temp_info['qq']))
            break
    else:
        print("没有您要找的信息....")


def print_all_info():
    """遍历学生信息"""
    print("序号\t姓名\t\t手机号\t\tQQ")
    i = 0
    for temp in info_list:
        # temp是一个字典
        print("%d\t%s\t\t%s\t\t%s" % (i, temp['name'], temp['tel'], temp['qq']))
        i += 1


def main():
    """用来控制整个流程"""
    while True:
        # 1. 打印功能
        print_menu()

        # 2. 获取用户的选择
        num = input("请输入要进行的操作(数字)")

        # 3. 根据用户选择,做相应的事情
        if num == "1":
            # 添加学生
            add_new_info()
        elif num == "2":
            # 删除学生
            del_info()
        elif num == "3":
            # 修改学生
            modify_info()
        elif num == "4":
            # 查询学生
            search_info()
        elif num == "5":
            # 遍历所有的信息
            print_all_info()
        elif num == "6":
            # 退出系统
            exit_flag = input("亲,你确定要退出么?~~~~(>_<)~~~~(yes or no) ")
            if exit_flag == "yes":
                break
        else:
            print("输入有误,请重新输入......")


        input("\n\n\n按回车键继续....")
        os.system("clear")  # 调用Linux命令clear完成清屏

# 程序的开始
main()

4.递归函数

递归是⼀种编程思想,应⽤场景:如果要遍历⼀个⽂件夹下⾯所有的⽂件,通常会使⽤递归来实现;

特点:

  • 函数内部⾃⼰调⽤⾃⼰
  • 必须有出⼝
1)应⽤:3以内数字累加和
# 3 + 2 + 1
def sum_numbers(num):
    # 1.如果是1,直接返回1 -- 出⼝
    if num == 1:
        return 1
    # 2.如果不是1,重复执⾏累加并返回结果
    return num + sum_numbers(num - 1)


sum_result = sum_numbers(3)
# 输出结果为6
print(sum_result)
2)递归求n的阶乘
#使用递归求n的阶乘
def factorial(n):
    if n==1:
        return 1
    return n*factorial(n-1)
3)第n个斐波那契数
#第n个斐波那契数
def Fibonacci(n):
    if n==1 or n==2:
        return 1
    return Fibonacci(n-1)+Fibonacci(n-2)

5.lambda 表达式

1)lambda语法
lambda 参数列表 : 表达式

lambda表达式的参数可有可⽆,函数的参数在lambda表达式中完全适⽤。

lambda表达式能接收任何数量的参数但只能返回⼀个表达式的值。

# 函数
def fn1():
    return 200
print(fn1)
print(fn1())

# lambda表达式
fn2 = lambda: 100
print(fn2)
print(fn2())

直接打印lambda表达式,输出的是此lambda的内存地址

2) 示例:计算a + b
fn1 = lambda a, b: a + b
print(fn1(1, 2))
3)lambda的参数形式

⽆参数

fn1 = lambda: 100
print(fn1())

一个参数

fn1 = lambda a: a
print(fn1('hello world'))

默认参数

fn1 = lambda a, b, c=100: a + b + c
print(fn1(10, 20))

可变参数:*args

fn1 = lambda *args: args
print(fn1(10, 20, 30))

这⾥的可变参数传⼊到lambda之后,返回值为元组。

可变参数:**kwargs

fn1 = lambda **kwargs: kwargs
print(fn1(name='python', age=20))
4) 带判断的lambda
fn1 = lambda a, b: a if a > b else b
print(fn1(1000, 500))
5)列表数据按字典key的值排序
students = [
    {'name': 'TOM', 'age': 20},
    {'name': 'ROSE', 'age': 19},
    {'name': 'Jack', 'age': 22}]
# 按name值升序排列
students.sort(key=lambda x: x['name'])
print(students)
# 按name值降序排列
students.sort(key=lambda x: x['name'], reverse=True)
print(students)
# 按age值升序排列
students.sort(key=lambda x: x['age'])
print(students)

输出结果:

[{'name': 'Jack', 'age': 22}, {'name': 'ROSE', 'age': 19}, {'name': 'TOM', 'age': 20}]
[{'name': 'TOM', 'age': 20}, {'name': 'ROSE', 'age': 19}, {'name': 'Jack', 'age': 22}]
[{'name': 'ROSE', 'age': 19}, {'name': 'TOM', 'age': 20}, {'name': 'Jack', 'age': 22}]

6.高阶函数

把函数作为参数传入,这样的函数称为高阶函数,高阶函数是函数式编程的体现。函数式编程就是指这种高度抽象的编程范式

1. 定义

需求:任意两个数字,按照指定要求整理数字后再进行求和计算。

  • 方法1
def add_num(a, b):
    return abs(a) + abs(b)


result = add_num(-1, 2)
print(result)  # 3
  • 方法2
def sum_num(a, b, f):
    return f(a) + f(b)


result = sum_num(-1, 2, abs)
print(result)  # 3

两种方法对比之后,发现方法2的代码会更加简洁,函数灵活性更高。

函数式编程大量使用函数,减少了代码的重复,因此程序比较短,开发速度较快

2)内置高阶函数map

map(function, list) 会根据提供的函数对指定序列做映射.

第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表.

#计算每一个元素的平方值
my_list = [1, 2, 3, 4, 5]

def f(x):
    return x ** 2

result = map(f, my_list)
print(type(result), result, list(result))

输出结果:

<class 'map'> <map object at 0x00000213DF912FA0> [1, 4, 9, 16, 25]
#首字母大写
my_list = ['smith', 'edward', 'john', 'obama', 'tom']

def f(x):
    return x[0].upper() + x[1:]


result = map(f, my_list)
print(list(result))

结果:

['Smith', 'Edward', 'John', 'Obama', 'Tom']
3)内置高阶函数reduce

reduce(function, list) 函数会对参数序列中元素进行累计.

函数将一个数据集合中的所有数据进行下列操作:

  1. 用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作.
  2. 得到的结果继续和序列的下一个元素做累积计算, 最终得到一个结果.
#计算列表中的累加和:
import functools

my_list = [1, 2, 3, 4, 5]


def f(x1, x2):
    return x1 + x2


result = functools.reduce(f, my_list)
print(result)

运行结果:15

4)内置高阶函数filter

filter() 函数用于过滤序列, 过滤掉不符合条件的元素, 返回一个 filter 对象, 如果要转换为列表, 可以使用 list() 来转换.

该接收两个参数, 第一个为函数, 第二个为序列, 序列的每个元素作为参数传递给函数进行判断, 然后返回 True 或 False, 最后将返回 True 的元素放到新列表中.

list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 1. 定义功能函数:过滤序列中的偶数
def func(x):
    return x % 2 == 0
# 2. 调用filter
result = filter(func, list1)
print(result)

print(list(result))

结果:

<filter object at 0x000002B6B6A03FA0>
[2, 4, 6, 8, 10]
#过滤列表中首字母为大写的单词:
my_list = ['edward', 'Smith', 'Obama', 'john', 'tom']


def f(x):
    return x[0].isupper()

result = filter(f, my_list)
print(list(result))

结果:[‘Smith’, ‘Obama’]

#找到列表中所有的张曼玉
l = ['林青霞','张曼玉','胡慧中','高圆圆','张曼玉']
result = list(filter(lambda ele:ele=='张曼玉',l))
print(result)
5)sort用法

sort用来对容器中元素进行排序

该接收两个参数, 第一个key为函数, 第二个为reverse是否翻转, 序列的每个元素作为参数传递给函数进行处理,最后会按照处理之后的数据进行排序

l = ['abcdef','ghf','treh']
l.sort(key=lambda ele:len(ele))
print(l) # ['ghf', 'treh', 'abcdef']

结果:[‘张曼玉’, ‘张曼玉’]

  • 20
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值