• 04-函数-课堂笔记


    一、复习

    '''
    字符编码
    文件头:py2 - ASCII  py3 - UTF-8
    三种字符串:u''  b''  r'' 
    u''.encode('utf-8')
    b''.decode('utf-8')
    str(b'', encode='utf-8')
    bytes(u'', encode='utf-8')
    
    文件操作
    三步骤:1.开的文件 2.操作文件(读写) 3.关闭
    简写:with open => 可以自动关闭文件流
    操作模式:
    主:r  w  a  x
    从:t  b  +
    
    seek:游标  (偏移量, 游标操作位置)  与b模式结合
    
    
    函数基础
    函数定义:def 函数名(): 函数体
    函数调用:函数名()
    函数的返回值:省略  空return  return一个值  return多个值 => 本质返回一个装有多个值的元组
    '''
    
    

    二、今日内容

    '''
    1.函数的参数:实参与形参
    2.函数对象:函数名
    3.名称空间与作用域:LEGB
    4.闭包:函数的嵌套定义
    5.装饰器:闭包的一种应用场景
    6.迭代器对象:迭代器,生成器,for迭代
    
    7.匿名函数
    8.内置函数
    9.三元表达式、列表、字典生成式
    10.模块
    
    '''
    

    三、如何定义函数

    '''
    1、功能的单一化
    2、函数内部需要外部的资源:通过函数的参数来实现
    3、函数执行后的结果需要告诉外界:通过返回值告诉给外界
    '''
    

    四、函数的参数

    形参与实参

    '''
    形参:在函数定义时()里出现的参数
    	-- 形参本身没有实际值(意义),在函数调用时,传入什么实参,形参就装有什么值
    实参:在函数调用时()里出现的参数
    	-- 实参有实际值(意义)
    	
    重点:函数调用传参:将实参的值赋值给形参 | 形参要获取外界的值只能通过实参进行获取
    '''
    
    def fn(a, b):  # a, b:形参
        pass
    
    a = 10
    fn(a, 20)  # a, 20:实参
    
    

    两种实参

    '''
    位置实参:
    1.传参两种方式:实参名 | 实参具体值
    2.必须按位置对形参进行传值
    
    
    关键字实参:
    1.传参两种方式:形参名=实参名 | 形参名=实参值
    2.可以指名道姓对形参进行传值,所以可以不用按位置进行传参
    '''
    
    def func(a, b, c):
        print(a, b, c)
    
    # func(10, b=20, 200)  报错:SyntaxError: positional argument follows keyword argument
    # 重点:两种实参在一起进行传参时:必须位置在前,关键字在后
    

    两大形参分类

    '''
    形参种类:
    1)位置形参
        -- 普通位置形参
        -- 默认值形参
        -- 可变长位置形参
    
    2)关键字形参
        -- 有默认值关键字形参
        -- 无默认值关键字形参
        -- 可变长关键字形参
    '''
    def fn(a, b, *, x, y):  # 位置形参:a, b  关键字形参: x, y
        pass
    
    '''
    重点:
    1.*为分水岭
    2.位置实参只能给位置形参进行传值
    3.关键字实参可以给位置形参与关键字形参进行传值
    '''
    

    两个带默认值的形参

    def fn2(a=10, *, x=20):
        print(a, x)
    fn2(100, x=200)
    # 总结:
    # 1.有默认值的参数可以不用传值
    # 2.*前有默认值的叫默认值参数,属于位置形参,可以被位置及关键字实参进行传值
    # 3.*后有默认值的叫有默认值的关键字形参,属于关键字形参,只能被关键字实参进行传值
    # 4.如果省略*, 有默认值的形参都是默认值参数
    
    

    不带默认值与带默认值形参结合使用

    def fn3(a, b=10, *, x, y=20, z):
        print(a, b, x, y, z)
    fn3(100, x=200, z=300)
    # 总结:
    # 1.没有默认值的必须传参,有默认值的可以传也可以不传
    # 2.位置有值的必须出现在无值之后,关键字顺序不做要求
    

    可变长位置形参与可变长关键字形参

    def fn4(a, b=10, *args, x, **kwargs):
        print(a, b, x)
        print(args)
        print(kwargs)
    fn4(10, 20, 30, x=100, y=200, z=300)
    # 总结:
    # 1.可变长是用来接收未接收完的值(接收0到n个):
    #   -- *args用来接收所有没有接收完的位置(只能接收位置实参)
    #   -- **kwargs用来接收所有没有接收完的关键字(只能接收关键字实参)
    # 2.*args必须出现在所以位置参数之后,**kwargs必须出现在所以参数之后
    
    
    # 常见应用场景
    # 假设第一个位置永远是参数name
    def func4(*args, **kwargs):
        name = args[0]  # 将name抽出来
    
    def func44(name, *args, **kwargs):
        # name 可以直接接收,省了抽出来的过程
        pass
    

    总结

    '''
    1.位置实参只能给位置形参传值
    2.关键字实参可以给位置及关键字形参传值
    3.有默认值的可以不用传参
    4.可变长位置形参只能接受位置实参,接受位置形参没有接收完的位置实参,存放到元组中
    5.可变长关键字形参只能接受关键字实参,接受关键字形参没有接收完的关键字实参,存放到字典中
    6.*args必须出现在所有位置形参之后,**kwargs必须在所有形参之后
    '''
    

    可变长整体传参:打散传值

    def fn(*args, **kwargs):
        print(args, kwargs)
        
    fn([1, 2, 3], {'a':1 , 'b': 2})  # =>接收到的 ([1, 2, 3], {'a':1 , 'b': 2})  {}
    fn(*[1, 2, 3], **{'a':1 , 'b': 2})  # =>接收到的 (1, 2, 3)  {'a':1 , 'b': 2}
    
    # 注:字符串也可以作为单列集合进行打散传递
    fn(*'abc')  # => ('a', 'b', 'c')  {}
    

    五、函数对象

    # 函数名就是存放了函数的内存地址,存放了内存地址的变量都是对象,即 函数名 就是 函数对象
    
    # 函数对象的应用场景
    # 1 可以直接被引用
    # 2 可以当作函数参数传递
    # 3 可以作为函数的返回值
    # 4 可以作为容器类型的元素
    
    # 功能体
    def add(n1, n2):
        return n1 + n2
    
    def low(n1, n2):
        return n1 - n2
    
    def jump(n1, n2):
        return n1 * n2
    
    # 完成功能
    def computed(n1, n2, fn):  # fn = add|low|jump
        res = fn(n1, n2)  # 调用具体的功能
        return res
    
    # 功能对应关系
    method_map = {  # 指令与函数对象的对应关系
        '1': add,
        '2': low,
        '3': jump
    }
    
    # 获取功能
    def get_method(cmd):
        if cmd in method_map:
            return method_map[cmd]  # 返回 add|low|jump
        return add  # 当指令错误,add作为默认功能
    
    while True:
        cmd = input('cmd: ')
        res = get_method(cmd)(10, 20)  # 根据指令获取功能并调用得到结果
        print(res)
    

    六、函数的嵌套调用

    # 函数的嵌套调用:在一个函数内部调用另一个函数
    # 求两个数最大值
    def max_two(n1, n2):
        if n1 > n2:
            return n1
        return n2
    
    # 求三个数最大值
    def max_three(n1, n2, n3):
        max = max_two(n1, n2)
        return max_two(max, n3)
    
    # 求四个数最大值
    def max_four(n1, n2, n3, n4):
        max = max_three(n1, n2, n3)
        return max_two(max, n4)
    print(max_four(20, 50, 30, 50))
    

    七、名称空间

    # 名称空间:存放名字与内存空间地址对应关系的容器
    # 作用:解决由于名字有限,导致名字重复发送冲突的问题 - 内置全局局部可以同时使用一个名字存放不同地址
    
    # 三种名称空间
    # Built-in:内置名称空间;系统级,一个;随解释器执行而产生,解释器停止而销毁
    # Global:全局名称空间;文件级,多个;随所属文件加载而产生,文件运行完毕而销毁
    # Local:局部名称空间;函数级,多个;随所属函数执行而产生,函数执行完毕而销毁
    
    # 加载顺序:Built-in > Global > Local
    # 	-- 采用堆栈存储数据的方式(压栈),导致内置最后被访问
    

    八、函数的嵌套定义

    # 函数的嵌套定义:在函数内部定义函数
    # 诞生的理由:一个函数想使用另一个函数内部的变量,可以定义在其内部
    def func():
        a = 10
        def fn():
            print(a)
        return fn
    
    new_fn = func()
    new_fn()
    

    两个与函数有关的关键字:global nonlocal

    # global:统一局部与全局的变量名
    num = 10
    def outer():
        # global num
        # num = 100
        def inner():
            global num
            num = 1000
            
    # nonlcal: 统一局部与嵌套局部的变量名
    def outer():
        num = 100
        def inner():
            nonlocal num
            num = 1000
    

    九、作用域

    # 作用域:名字起作用的范围
    # 作用:解决同名字可以共存问题 - 不同作用域相同名字的值都能在其作用域范围下进行使用
    '''
    四种作用域: LEGB
    Built-in:内置作用域 - 所有文件所有地方都可以被访问
    Global:全局作用域 - 在当前文件的所有位置
    Enclosing:嵌套作用域 - 自身内部与内部的子函数
    Local:局部作用域 - 只有自身内部
    '''
    # 加载顺序:Built-in > Global > Enclosing > Local
    # 访问(查找)顺序:报错 < Built-in < Global < Enclosing < Local
    # 作用范围:Built-in > Global > Enclosing > Local
    

    十、闭包

    # 闭包:定义在函数内部的函数,这个内部的函数就是闭包
    
    # 应用场景:
    # 1.可以去使用其他函数的内部变量,且还可以保证调用位置不变(闭包的函数对象作为那个函数的返回值)
    def outer():
        count = 3000
        def fn():
            print(count)  # 能使用outer内部的变量count
        return fn
    # 还是在外界调用
    outer()()  # outer()() => fn() => 调用fn
    
    
    # 2.延迟执行(外层函数可以为内存函数传递参数)
    import requests
    def outer(url):
        def show_html():
            response = requests.get(url)
            print(response.text)
        return show_html
    
    # 制作 爬百度与新浪的 函数对象
    show_baidu = outer('https://www.baidu.com')
    show_sina = outer('https://www.sina.com.cn')
    
    # 延迟到需求来了,需要爬百度,就用百度函数对象,需要爬新浪,就用新浪函数对象
    show_baidu()
    show_sina()
    show_baidu()
    

    十一、装饰器

    # 装饰器:装饰器就是闭包的一个应用场景
    #       -- 外层函数与内存函数形成的闭包结构的一种综合使用
    
    # 重点:开放封闭原则
    # 开放:拓展功能的点是开放的 - 可以为之前的函数添加新功能
    # 封闭:1.不能改变原函数的源代码  2.还有通过原函数的函数对象来调用函数
    
    def huaping():
        print('插花功能')
    
    temp = huaping
    def my_huaping():
        temp()
        print('观赏功能')
    huaping = my_huaping
    
    huaping()
    
    # ----------------------------------------
    
    def huaping():
        print('插花功能')
    
    def outer(temp):  # temp = huaping
        def my_huaping():
            temp()
            print('观赏功能')
        return my_huaping
    huaping = outer(huaping)  # huaping = my_huaping
    
    huaping()
    
    
    # ----------------------------------------------
    def outer(temp):  # temp = huaping
        def my_huaping():
            temp()
            print('观赏功能')
        return my_huaping
    
    @outer  # huaping = outer(huaping)
    def huaping():
        print('插花功能')
        
    huaping()
    
    
    # ------------------------------------------
    # 被装饰的函数可能有参有返:装饰器模板,可以满足所有参数,且能装饰原函数返回值
    def outer(func):  # temp = huaping
        def inner(*args, **kwargs):
            pass
            res = func(*args, **kwargs)
           	pass
        	return res
        return inner
    
    @outer
    def any_method():
        pass
    
    

    装饰器案例

    # 为登录功能添加账号检验功能:必须是3个及以上英文字母组成
    def check_user(func):
        def inner(user, pwd):
            if not (user.isalpha() and len(user) >= 3):
                return '账号不合法'
            res = func(user, pwd)
            return res
        return inner
    
    # 为登录功能添加密码检验功能:必须是3个及以上英文字母或数字组成
    def check_pwd(func):
        def inner(*args, **kwargs):
            pwd = args[1]
            if not (pwd.isalnum() and len(pwd) >= 3):
                return '密码不合法'
            res = func(*args, **kwargs)
            return res
        return inner
    
    # 对登录结果的修饰装饰器:True=>登录成功 False=>登录失败
    def change_res(func):
        def inner(*args, **kwargs):
            res = func(*args, **kwargs)
            if res == True:
                return '登录成功'
            return '登录失败'
        return inner
    
    
    # 装饰器被执行的过程是从上至下
    @check_user  # login = check_user(func=login) = inner
    @check_pwd
    @change_res
    def login(user, pwd):  # 被装饰的函数对象
        if user == 'owen' and pwd == '123':
            return True
        return False
    
    user = input('user: ')
    pwd = input('pwd: ')
    res = login(user, pwd)
    
    print(res)
    
  • 相关阅读:
    Pycharm Debug调试心得
    看了一些东西,发现一些用css实现一些东西的小技巧就记录下来
    使用js创建10*10方块
    用JS获取窗口和元素的大小
    jQuery笔记
    DOM学习中的小笔记
    常用的sql语句
    C#比较两个字符串的相似度【转】
    .net Core学习笔记之MemoryCache
    初学nodejs之安装Express中遇到的问题: error: option `-v, --view <engine>' argument missing
  • 原文地址:https://www.cnblogs.com/qiangyuzhou/p/10899863.html
Copyright © 2020-2023  润新知