• Python编程学习基础笔记04


    六、函数

    6.1 函数基础

    6.1.1 函数定义

    ''''
    函数:复用
    格式:
    def 函数名([参数],...)
        代码
    
    sample:
    def get_name():
        pass
    def search():
        pass
    
    代码:
        封装重复内容
    函数调用:函数名()
    '''
    import random
    def gernerate_code():
        # 定义一个空字符串
        ver_code = ''
        # 准备一个字符串,包含字母和数字
        source = 'QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890'
        for i in range(4):
            # 可以直接随机取一个字符
            r = random.choice(source)
            # 将每次获取到的值拼接为4为的字符串
            ver_code += r
        print(ver_code)
    
    print(gernerate_code) #<function gernerate_code at 0x0000020BCFE3C2F0>
    '''
    定义一个login函数
    用户名:admin,密码:123456
    验证用户名和密码是否正确
    '''
    def login():
        while True:
            #输入用户名或手机号
            login_name = input("请输入用户名/手机号:")
            passwd = input("请输入密码:")
            if login_name == 'admin' and passwd == '123456':
                break
                print('登录成功')
            else:
                print('用户名或密码有误,请重新输入')
    
    #验证函数是否可用?调用函数
    gernerate_code()
    login()
    

    6.1.2 带参数的函数

    '''
    参数:
        1,无参数
        2,有参数
    无参数:
    def 函数名()
        代码
    有参数:
    def 函数名(参数1,参数2,...)
        代码
    参数就是在调用函数时,往函数体内传值
    默认值参数:在定义函数的时候,有一个或多个参数已经赋值好
        def 函数名(参数1,参数2,参数3=值,参数4=值):
            pass
        调用特点:
            函数名(值1,值2,值3)
        注意:
            定义函数时,普通参数要位于默认值参数前面
            调用时,默认参数顺序时定义时的顺序,可以指定关键字参数赋值,改变顺序
    '''
    #login 带参数,n表示允许输入的错误此次数
    def login(n):
        m =0
        while m < n:
            m += 1
            #输入用户名或手机号
            login_name = input("请输入用户名/手机号:")
            passwd = input("请输入密码:")
            if login_name == 'admin' and passwd == '123456':
                break
                print('登录成功')
            else:
                print('用户名或密码有误,请重新输入')
    #数字累加函数1 - n
    def accumulation(n):
        sum = 0
        m = 0
        while m <= n:
            sum += m
            m += 1
        print(sum)
    
    #带默认值的函数,number和school带默认值,不传入参数时,使用默认值
    def borrow_book(bookname,username,number=1,school='天大'):
        print(f'欢迎进入{school}借书系统>>>>>>')
        print(f'{username}借阅了{bookname},共{number}本')
    #函数调用
    # login(3)
    accumulation(10)
    borrow_book('Forrest','红楼梦') #红楼梦借阅了Forrest,共1本
    borrow_book(username='Forrest',bookname='红楼梦') #Forrest借阅了红楼梦,共1本
    borrow_book('Forrest','红楼梦',2) #红楼梦借阅了Forrest,共2本
    #普通参数也带上关键字后,默认参数不能直接给值
    borrow_book(username='Forrest',bookname='红楼梦',number=2,school='北大') #SyntaxError: positional argument follows keyword argument
    

    可变参数:参数类型为列表,元组和集合

    '''
    参数类型:
    1,列表
    2,可变参数:
        *args
        **kwargs
    3,装包和拆包 --> 对应可变参数
        装包:函数装包的过程,定义函数是,参数加星*
        def 函数(*args): --> 此时函数会出现装包
            pass
        拆包:函数拆包的过程,调用函数时,参数加星*, 拆列表,元组和集合
        调用函数时:
            函数(*list) | 函数(*tuple) |函数(*set)
    '''
    #验证示例讲解
    #参数和变量个数相等
    a,b,c = 1,2,3
    print(a)
    print(b)
    print(c)
    #参数和变量个数不等,带星号的表示一个容器,多余的参数都给带星的
    a,*b,c = 1,2,3,4,5,
    print(a)
    print(b) #[2, 3, 4]
    print(c)
    #参数和变量个数不等,带星号的表示一个容器,多余的参数都给带星的
    *a,b,c = (1,2,3,4,5)
    print(a) #[1, 2, 3]
    print(b)
    print(c)
    #参数类型为列表
    list1 = [1,5,66,34,22,7,77,89,100,25,50]
    #从列表中删除小于50的数,list_1-->形参,可以随便定义
    def del_from_list(list_1):
        n = 0
        while n < len(list_1):
            if list_1[n] < 50:
                list_1.remove(list_1[n])
            else:
                n += 1
        print(list_1)
    #可变参数,重写求和函数,*星号是关键,装包,之后的变量名可以任意,但通常用args
    def get_sum(*args):
        s = 0
        for i in args:
            s += i
        print(s)
    #函数调用,list1 实参
    del_from_list(list1)
    get_sum(1,2) #参与会以元组的形式赋值给变量
    get_sum(1,2,3,4,5)
    #调用是加*,星号表示拆包
    get_sum(*list1) #382
    

    可变参数:带2颗星的情况, 同时有1颗星 和2颗星的情况

    '''
    可变参数:**kwargs, 关键字参数
    在函数调用时必须传递关键字参数,才可以转换为key:value,装载到字典中
    '''
    #key word
    def show_book(**kwargs):
        print(kwargs)
    
    #同时带了*args 和 **kwargs
    def show_story(*args,**kwargs):
        print(args) #()
        print(kwargs) #{}
    #调用函数
    show_book() #{}
    # show_book('红楼梦') #TypeError: show_book() takes 0 positional arguments but 1 was given
    #可以加多个关键参数
    show_book(bookname='红楼梦',author='曹雪芹') #{'bookname': '红楼梦', 'author': '曹雪芹'}
    #拆包,必须加2颗星
    book = {'bookname': '红楼梦', 'author': '曹雪芹'}
    show_book(**book) #{'bookname': '红楼梦', 'author': '曹雪芹'}
    
    #带* ** 的情况
    show_story('小红','小花') #('小红', '小花')
    show_story('小红','小花', story='星际联邦')
    '''
    ('小红', '小花')
    {'story': '星际联邦'}
    '''
    #字符拼接,'-' 以此为分隔符
    result = ''.join(['a','b','c'])
    print(result) #abc
    result = '-'.join(['a','b','c'])
    print(result) #abc
    

    6.2 函数应用

    6.2.1 函数注释

    '''
    在函数体内加上注释,给使用函数的人以提示信息
    '''
    

    6.2.2 函数返回值

    return 会结束函数调用,并返回值。return不仅会结束循环,还会结束函数

    '''
    参数:外界向函数内传值
    返回值:函数里面的内容值向往传递
    def function():
        ...
        return xx
    当函数调用时,通过return向往返回值
    注意: 只有函数有返回值,外部需要有变量来接收
         return 后可跟一个或多个值,逗号分隔
         如果时多个值,返回的是一个元组,多个值被封装在元组中
            示例: retur a,b,c
                结果 (a,b,c)
    '''
    #将计算结果作为返回值,返回一个值
    def get_sum(*args):
        s = 0
        for i in args:
            s += i
        #返回计算结果
        return s
    
    #返回多个值
    def get_max_min(numbers):
        #先排序:冒泡排序
        for i in range(len(numbers)-1):
            for j in range(0,len(numbers)-1-i):
                if numbers[j]>numbers[j+1]:
                    numbers[j],numbers[j+1] = numbers[j+1],numbers[j]
        #获取头和尾
        min = numbers[0]
        max = numbers[-1]
        #返回
        return min,max
    #在外部定义一个变量total来接收函数的返回值
    total = get_sum(1,2,3,5)
    x = 100
    x = x + total
    print(x) #111
    
    list1 = [3,8,6,11,25,43,66,89,36,77,99,66]
    #return返回2个值(min,max),使用2个变量来接收
    min,max = get_max_min(list1)
    print(min,max)
    

    6.3 函数高级

    6.3.1 全局变量和局部变量

    全局变量:声明在函数外部的变量
    局部变量:声明在函数内部的变量,使用范围仅限于函数内部

    '''
    全局和局部变量:
        全局变量:声明在函数外部的变量
        局部变量:声明在函数内部的变量,使用范围仅限于函数内部
        注意:
            函数内部可以直接使用全局变量,但是不能直接修改全局变量
            如果想修改全局变量,则必须使用关键字 global
        global 关键字的添加:
    '''
    a = 100
    def test1():
        #局部变量,函数优先使用
        a = 0
        b = 8
        print('a = ',a)
        print('b = ',b)
    def test2():
        #局部变量,函数优先使用,如果函数体内定义的同名的变量
        b = 8
        #这里取到的a就是全局变量a
        print('a = ',a)
        print('b = ',b)
    def test3():
        #声明a为全局变量
        global a
        #如果部声明a为全局变量,函数内部无权操作a
        a -= 10
        #这里取到的a就是全局变量a
        print('a = ',a)
    #函数调用
    test3()
    test1()
    test2()
    

    6.3.2 可变和不可变类型

    '''
    全局和局部变量:
    global 关键字的添加:
        只有不可变的类型,才需要添加关键字global
        可变类型,不需要添加关键字global
    可变和不可变类型:
        不可变:当改变变量值时,地址发生了改变
            类型:int, str,float,bool, tuple
        可变:内容发生改变,但是地址没有发生改变
            类型:list, dict, set
    '''
    #可变变量
    library = ['红楼梦','水浒传','西游记','三国演义']
    print(id(library)) #2425797567112
    library.append('窦娥冤')
    print(id(library)) #2425797567112
    #不可变变量
    a = 100
    print(id(a)) #140712806182832
    a = 80
    print(id(a)) #140712806182192
    s = 'abc'
    print(id(s)) #1698608322912
    s = 'def'
    print(id(s)) #1698608946848
    t1 = (1,2,3)
    print(id(t1)) #1908556126968
    t1 = (1,2,3,4)
    print(id(t1)) #1908556105112
    #添加图书
    def add_book(bookname):
        if bookname not in library:
            library.append(bookname)
            print(f'{bookname}添加成功')
        else:
            print('此书已经存在')
    #展示全部图书
    def show_books(books):
        for book in books:
            print(book)
    #函数调用
    add_book('西厢记')
    show_books(library)
    

    6.3.3 引用及参数值传递

    '''
    引用:
    1,不是在函数中使用,可以通过sys.getrefcount(a)查看引用个数
        del 变量名 --> 表示删除了一个引用
    2,函数的引用:
        必须要分清传递的值是可变还是不可变类型
        如果可变,里面发生改变,外层可以看到改变后的内容
        如果是不可变,里面发生改变,不会影响外部的变量值
    '''
    import sys
    
    list1 = [1,2,3,4,5]
    list2 = list1 #list1 将其引用地址给list2赋值
    list3 = list1
    #获取变量被引用的次数,这里查的是地址
    print(sys.getrefcount(list1)) #4
    del list2
    print(sys.getrefcount(list1)) #3
    
    def test(n1):
        #n1是局部变量
        for i in range(n1):
            print('--->',i)
        n1 += 1  # 这里改变的只是局部变量的值
    
    n = 9
    #调用test
    test(n)
    print(n) #9
    
    def test1(l):
        #判断传入的是列表
        if isinstance(l,list):
            for i in l:
                print(i)
            #在第0个位置插入新的值
            l.insert(0,8) #可变参数,改变的是全局参数值
        else:
            print('不是列表类型')
    
    #调用test1
    test1(list1)
    print(list1) #[8, 1, 2, 3, 4, 5]
    

    6.3.4 练习:停车计费系统

    '''
    停车计费数据结果:
    [{'车牌':[进入时间,0]},{'车牌':[进入时间,出场时间]}]
    15分钟 1元
    1小时 4 元
    
    停车场变量--> 全局变量
    '''
    import  random
    #初始化停车场数据
    car_park = []
    #记录车辆入场停车,车牌和时间
    def veh_enter():
        print('欢迎进入AAA停车场')
        plate = input('请输入车牌号:').strip()
        #构建结构{'车牌':[0,5]}
        car = {}
        car[plate] = [0]
        #添加到car_park
        car_park.append(car)
        print(f'欢迎{plate}入场停车!')
    #记录车辆出场,车牌和时间
    def veh_exit():
        #出场扫描
        plate = input('请输入车牌号:').strip()
        #判断此车是否有入场记录
        for car in car_park:
            if plate in car:
                #记录出场时间
                time = random.randint(0,24)
                time_record = car.get(plate)
                time_record.append(time)
                #计算费用,退出循环
                total = time * 4
                print(f'{plate}停车{time}小时,应缴费:{total}元')
                break
        else:
            print(f'{plate}没有入场记录!')
    #调用
    veh_enter()
    veh_exit()
    

    6.4 闭包

    函数只是一段可执行代码,编译后就固化了,每个函数在内存中只有一份实例,得到函数入口点便可执行。函数还可以嵌套函数,即函数内部可以定义另一个函数,这就会产生闭包的问题。

    '''
    函数嵌套:
    变量查找顺序:内层函数 --> 外层函数 --> 全局 --> 系统 builtins
    闭包:
    1,是嵌套函数
    2,内部函数引用了外部函数变量
    3,返回值是内部函数
    '''
    #嵌套
    def outer():
        a = 100
        def inner():
            b = 200
            # b += a  #内部函数可以使用外部函数的变量,但是不能改变外部变量
            #如果想修改外部变量,需要在内部函数中加上: nonlocal
            nonlocal a
            a += b #内部函数不能改变外部变量
            print('这是内部函数',b)
        result = locals() #locals()表示查看函数中的局部变量,以字典形式返回
        print(result) #{'a': 100, 'inner': <function outer.<locals>.inner at 0x000001E39698E730>}
        #调用inner
        inner() #这是内部函数 300
    #函数调用
    outer()
    
    #闭包 = 函数块 + 引用环境
    def outer1(n):
        a = 10
        def inner():
            b = a + n
            print('内部函数:',b)
        return inner
    
    r = outer1(5)
    print(r) #<function outer1.<locals>.inner at 0x0000020177D0E7B8>
    r() #内部函数: 15
    

    6.5 装饰器

    6.5.1 装饰器基础

    '''
    装饰器:
    遵循开放封闭原则,在不改变原函数的情况下,扩展了函数功能
    定义:
    def xxx(func):
        def xxx():
            ...
            func()
            ...
            return xxx
        return yyy
    装饰:
    @装饰器名  #原函数 = 装饰器名(原函数)
    def 原函数():
        pass
    功能:
    1,引入日志
    2,函数执行时间统计
    3,执行函数前的预备处理
    4,执行函数后的清理功能
    5,权限校验等场景
    6,缓存
    '''
    #定义一个装饰器
    def decorator(func):
        print('------------->1')
        def wraper():
            func() # 先执行外部函数 house
            print('刷漆')
            print('铺地板')
            print('软装')
            print('精装房')
        print('------------->2')
        return  wraper
    
    @decorator #开始调用decorator,house = decorator(house) 先执行打印 ------------->1 ------------->2
    def house(): #将house作为变量传入,类似 func = house
        print('毛坯房')
    #调用函数
    house()
    '''
    执行结果:
    ------------->1
    ------------->2
    毛坯房
    刷漆
    铺地板
    软装
    精装房
    '''
    

    6.5.2 带参数的装饰器

    '''
    带参数的装饰器:
    如果原函数有参数,装饰器内部也要有参数
    '''
    #定义一个装饰器,*args,**kwargs 可以接任意变量
    def decorator(func):
        def wraper(*args,**kwargs): #address = ’北京‘,*args是一个元组
            func(*args,**kwargs) # func 就是 house
            print('刷漆')
            print('铺地板')
            print('软装')
            print('精装房')
        return  wraper
    
    @decorator #开始调用decorator
    def house(address): #将house作为变量传入,类似 func = house
        print(f'位于{address}的毛坯房')
    
    @decorator #开始调用decorator
    def workplace(address,area):
        print(f'位于{address}的毛坯房,面积{area}平米')
    
    @decorator #开始调用decorator
    def hotel(name,address,area=40):
        print(f'{name}酒店,位于{address}的毛坯房,单间面积{area}平米')
    #调用函数
    house('北京') # house 就是 wraper
    
    workplace("北京通州",1000)
    
    hotel('全季',address='北京') #如果没有**kwargs 运行会报错
    

    6.5.2 带返回值的装饰器

    '''
    装饰器修饰有返回值的函数:
    原函数有返回值,装饰器内部函数也需要返回值
    '''
    #定义一个装饰器,*args,**kwargs 可以接任意变量
    def decorator(func):
        def wraper(*args,**kwargs): #address = ’北京‘,*args是一个元组
            r = func(*args,**kwargs) # func 就是 house
            print(f'预计费用是:{r}元')
            print('刷漆')
            print('铺地板')
            print('软装')
            print('精装房')
            return 60000 # 原函数有返回值,wrapper也需要返回值
        return  wraper
    @decorator #开始调用decorator
    def house(address): #将house作为变量传入,类似 func = house
        print(f'位于{address}的毛坯房')
        return 50000
    #调用函数
    house('北京') # house 就是 wraper
    

    6.6 递归函数

    如果一个函数在内部不调用其他任何函数,而是自己本身的话,这个函数就是递归函数。

    '''
    如果一个函数在内部不调用其他任何函数,而是自己本身的话,这个函数就是递归函数
    遵循:
    1,必须要有出口
    2,每次递归,要向出口靠近
    
    '''
    #
    def test():
        print('----------test-----------')
        # 调用a()
        a()
    
    def a():
        print('----------aaaa-----------')
        #调用a()
        a()
    
    
    # 调用a()
    # a()
    
    #打印数字1-10,递归函数实现
    def num(i):
        if i == 10:
            print(i)
        else:
            print(i)
            i += 1
            num(i)
    
    #调用num(),从1开始
    # num(1)
    
    #数字1-10的累加和,递归函数实现
    total = 0
    def sum(i):
        global total
        if i == 11:
            print('over',total)
        else:
            total += i
            i += 1
            sum(i)
    #使用返回值求累加
    def sum1(i):
        if i == 10:
            return 10
        else:
            return i + sum1(i+1)  # 逐层向下递归,但是到最后i=10之后才有返回,然后再逐层返回值进行计算
    #调用sum(),从1开始
    # sum(1)
    
    r = sum1(1)
    print(r)
    

    6.7 匿名函数

    6.7.1 匿名函数定义

    '''
    用lamda关键词可以创建小型匿名函数,省略了def声明函数的标准步骤
    匿名函数定义格式:
    lamda 参数列表:返回值表达式
    '''
    #定义标准函数
    def test(a):
        return a+1
    #使用变量来接收函数返回值
    result = test(5)
    print(result)
    
    #定义匿名函数,由于没有函数名,使用r来接收
    r = lambda a:a+1
    result = r(6)
    print(result)
    
    #定义匿名函数,多个参数
    r = lambda x,y: x+y
    result = r(6,7)
    print(result)
    

    6.7.2 匿名函数的使用场合

    '''
    匿名函数的使用场合:
    匿名函数作为参数来使用
    '''
    #定义标准函数
    def test():
        print('------test------')
    def func(a,f):
        print('--------->',a)
        f()
    #使用变量来接收函数返回值
    func(5,test)
    
    def func1(a,f): #lambda x:x**2
        print('>>>>>>>>>>',a)
        r = f(a)
        print('=====>',r)
    
    #调用func1,因为f带返回值,这里用匿名函数来赋值,多数情况,匿名函数放在参数位置
    func1(8,lambda x:x**2)
    

    6.8 高阶函数

    函数可以作为变量来使用。既然变量可以指向函数, 函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数。同样,可以把一个函数作为另一个函数的返回值。这种函数的使用方式,称之为高阶函数。

    '''
    高阶函数:
        一个函数的参数是另一个函数
    系统高阶函数:
        max,min,sorted, filter,map,reduce
    '''
    #普通查找最大值
    from functools import reduce
    
    m = max(5,6)
    print(m)
    
    #列表内查找最大值
    m = max([2,5,8,3,11,56,39,22])
    print(m)
    
    #匿名函数,找最大年龄
    list1 = [('Lily',25),('Tony',19),('Jessy',21),('Tomas',28),('Lucy',26),('Rose',29)]
    m = max(list1,key= lambda x:x[1])
    print(m)
    
    #找最小年龄
    m = min(list1,key= lambda x:x[1])
    print(m)
    
    #按年龄排序
    m = sorted(list1,key= lambda x:x[1])
    print(m) #[('Tony', 19), ('Jessy', 21), ('Lily', 25), ('Lucy', 26), ('Tomas', 28), ('Rose', 29)]
    
    #按年龄排序,倒序
    m = sorted(list1,key= lambda x:x[1],reverse=True)
    print(m) #[('Rose', 29), ('Tomas', 28), ('Lucy', 26), ('Lily', 25), ('Jessy', 21), ('Tony', 19)]
    
    #过滤 大于20岁的,lambda 返回值是真或假,返回值必须是bool类型,结果为True才符合过滤条件
    m = filter(lambda x:x[1]>20,list1)
    print(m) #<filter object at 0x0000020A2EDED748>, 返回的是可迭代对象
    #将m强转为list
    print(list(m)) #[('Lily', 25), ('Jessy', 21), ('Tomas', 28), ('Lucy', 26), ('Rose', 29)]
    
    #映射map,通过匿名函数指明提取内容,并对内容进行加工
    ma = map(lambda x:x[1]+1,list1)
    print(ma) #<map object at 0x000001FF6FCEE710>
    print(list(ma)) #[26, 20, 22, 29, 27, 30]
    
    ma = map(lambda x:x[0].title(),list1)
    print(ma) #<map object at 0x0000013E7233E860>
    print(list(ma)) #['Lily', 'Tony', 'Jessy', 'Tomas', 'Lucy', 'Rose']
    
    #reduce,对一个序列进行压缩运算,最后得到一个值
    r = reduce(lambda x,y:x+y,[1,2,3,4,5])
    print(r) #15
    
  • 相关阅读:
    centos下nginx的启动
    CentOS7.0安装Nginx 1.7.4
    序员的自我修养
    消息队列 rabbitMQ 的一些操作
    centos linux7的一些操作
    Windows 10 Install rabbitmq-server-3.6.9
    Redis 3.2.100 Windows 32位下载
    Redis配置文件详解
    yii2优化
    mysql中的schema 等价于database,相当于一个数据库
  • 原文地址:https://www.cnblogs.com/orange2016/p/16417375.html
Copyright © 2020-2023  润新知