• python基础 :函数 装饰器,迭代器,面向过程编程


    目录

    函数 装饰器,迭代器,面向过程编程

    1、什么是函数?

    def 函数名()
    

    参数:

    参数:

    在函数的定义阶段,写在括号中变量名就是形参
    

    实参:

    在函数的调用阶段,写在括号中的具体的值就是实参
    
    是在调用函数的时候生效,函数执行结束关系解除
    

    注释

    1、要写当前函数具体的功能
    2、解释当前函数参数作用
    3、解释当前函数返回值的特点
    
    函数体代码:函数的具体功能
    

    函数的返回值:

    1、不写返回值

    ython中所有的函数都有返回值,不写默认为None
    

    2、写return,返回一个值

    1、return
    函数体代码结束的标识,默认None
    2、return None
    函数体代码结束的标识,默认None
    3、return 值
    可以是python的任意数据类型
    

    3、写return,返回多个值

    return 值1,值2,值3...
    以逗号隔开多个值,可以返回多个任意类型的值,最后以元组的形式返回给调用者
    
    return [值1,值2,值3...]
                    自己指定返回的数据类型
    
                       def index(x,y,z):
                            return x,y,z
    
    
                       a,*_ = index(1,2,3)
    
                       print(a,*_)
    

    4、参数的详细描述

    1、位置参数

    1、位置参数
    在函数定义阶段按照顺序从左到右书写的变量名就叫位置形参
    
    在函数调用阶段按照顺序从左到右书写的具体的值就叫位置实参
    
    位置参数定义之后一定要传递参数
    
    

    2、关键字参数

    在函数调用阶段,以key=value形式进行,关键子参数
    
    

    3、默认值参数

    在函数定义阶段提前给形参赋值的操作就叫默认值参数
    
    

    4、可变长参数

    *
    **
    
    * 在函数定义阶段:接收所有溢出的位置参数,将接受的值以元组的形式传入* 后面的变量中
    * 在函数调用阶段:将列表、元组、字符串、集合等可以使用的for循环的容器类型打散成位位置参数
    
    ** 在函数定义阶段:接收所有溢出的关键字参数,将接受的值以字典的形式传入** 后面的变量中
    ** 在函数调用阶段:将字典打散成关键字参数传入形参
    
    

    5、定义函数的三种形式

    1、无参函数:

    def index():
        print("from index")
    
    

    2、有参函数:

    def func(x,y):
        print(x,y)
    
    

    3、空函数

    def register():
         pass
    def login():
    	pass
                            。。。
    
    

    命名关键字参数

    # 定义在* 和**之间
                # 在给命名关键字传值的时候一定要以关键字形式传递
    
                def index(x, y, z, *args, a=1, b, **kwargs):
                    print(x, y, z)
                    print(args)
                    print(a, b)
                    print(kwargs)
    
    
                index(1, 2, 3, 354353, 4342, 3213123, a=111, b=222, c=333, d=444)
    
    
    

    函数对象

    1.函数对象什么?

    函数的名字就是函数对象,函数名指向的是函数的内存地址。
    
    

    函数对象四大特征:

    1.函数名可以被的引用

    def index()
    	print('from index')
    a = index
    a()  #直接加括号调用
    
    
    from index
    
    

    2.可以当作参数传给一个函数

    def func():
        print('123')
    def func1(new):
        new()
    func1(func)
    
    
    123
    
    

    3.可以当作一个返回值。

    def func():
        print('123')
        return func
    
    msg = func()
    print(msg)
    msg()
    
    
    123
    <function func at 0x000002B054691F78>
    123
    
    

    4.可以当作容器类型的元素。

    dic = {}
    
    def abc():
        print('oldboy')
    
    dic['a'] = abc
    
    print(dic)
    
    res= dic['a']
    res()
    
    
    {'a': <function abc at 0x00000284A3D11EE8>}
    oldboy
    
    

    列:

    def register():
        print('register')
    
    
    def login():
        print('login')
    
    
    def shopping():
        print('shopping')
    
    
    def pay():
        print('pay')
    
    
    func_dic = {
        '1': register,
        '2': login,
        '3': shopping,
        '4': pay
    }
    
    def main():
        while True:
            print("""
                1、注册
                2、登录
                3、购物
                4、付款
                5、退出
            """)
            choice = input("请输入对应的编号:").strip()
            if choice == '5':
                break
            if choice not in func_dic:
                continue
            else:
                func_dic[choice]()
    
    main()
    
    

    函数对象的应用:

    补充--》可以优雅地取代if分支
    
    

    函数的嵌套

    函数嵌套定义: 让内层函数封闭起来,不让外部直接调用。
    
    
    函数的嵌套调用:在函数内调用函数
    
    
    def f1():
        def f2():
            print('from f2')
        f2()
    
    f1()
    from f2
    
    
    # 函数的嵌套定义:
    def index():    
    	def home():        
    		print("from home")    
    	home()
    index()
    
    

    名称空间

    什么是名称空间?

    用来存放名字的,名称空间是一个在内存中的空间。
    
    

    名称空间的分类?

    1.内置名称空间:

    python提前给你的定义完的名字,就是存在内置名称空间,   简称:存放内置方法
    
    

    2.全局名称空间

    除了内置和局部就是全局

    存放于文件级别的名字,就是全局名称空间
    if while for 内部定义的名字执行之后都存放于全局名称空间
    
    

    3.局部名称空间

    函数内部的定义的变量/函数

    函数内部定义的所有名字都是存放与当前函数的内置名称空间
    
    

    生命周期:

    1、内置名称空间

    在python解释器启动的时候生效,关闭解释器的时候失效

    2、全局名称空间

    当你启动当前这个py文件的时候生效,当前页面代码执行结束之后失效

    3、局部名称空间

    当你调用当前函数时生效,函数体最后一行代码执行结束就失效名称空间的查找顺序:

    名称空间的查找顺序:内置 --》 全局 --》 局部
    				局部:局部 > 全局 > 内置
        			全局:全局 > 内置  # 内置再找不到就报错
    
    
    函数内部使用的名字,在定义阶段已经规定死了,与你的调用位置无关
    
    

    作用域的分类

    全局作用域

    全局可以调用的名字就存在于全局作用域
    内置名称空间+全局名称空间
    
    

    局部作用域

    局部可以调用的名字就存放与局部作用域局部名称空间
    
    

    需要注意的是:作用域关系在函数定义阶段就固定死了,与函数的调用无关。

    global

    局部的可以修改全局的

    修改全局作用域中的变量。
    x = 1
    
    def f1():
        x = 2
    
        def f2():
            #         global x  # 修改全局
            x = 3
        f2()
    
    f1()
    print(x)
    
    #  1
    
    
    只有可变类型可以在局部修改外部变量的值
    
    

    nonlocal

    局部的修改外层局部的

    x = 1
    
    def f1():
        x = 2
    
        def f2():
            #         nonlocal x
            x = 3
    
        f2()
        print(x)
    
    
    f1()
    2
    
    
    x = 1
    
    def f1():
        x = 2
    
        def f2():
            nonlocal x
            x = 3
    
        f2()
        print(x)
    
    f1()
    3
    
    

    命名关键字参数

    定义在* 和**之间# 在给命名关键字传值的时候一定要以关键字形式传递# 关键字参数一定不能放在位置参数前面

    1.可变长参数

    可变长参数:在调用函数时,参入的参数个数可以不固定。

    调用函数时,传值的方式莫非两种,一种是位置实参,另一种是关键字实参,因此形参也必须的有两种解决方式,以此来分别接收溢出的位置实参(*)也关键字实参(**)

    一.可变长形参之*

    形参中的会将溢出的位置实参全部接收,然后存储元组的形式,然后把元组赋值给后的参数。需要注意的是:*后的参数名约定俗成为args。

    二 .可变长实参之*

    实参中的会将后参数的值循环取出,达三成位置实参。以后但凡碰到实参中带的,他就是位置实参,应该马上打散成位置实参去看。

    三. 可变长实参之**

    形参中的** 会将溢出的关键字实参全部接收,然后存储字典的形式,然后把字典赋值给** 后的参数。需要注意的是:**后的参数名约定俗成为kwargs。

    def func(**kwargs):
        print(kwargs)
    func(a=5)  #{"a":5}
    
    

    四 .可变长实参之**

    实参中的会将** 后参数的值循环取出,打散成关键字实参。以后但凡碰到实参中带**的,它就是关键字实参,应该马上打散成关键字实参去看。

    五. 关键字形参

    现在有一个需求,函数的使用者必须按照关键字实参传。

    def register(x, y, **kwargs):
        if 'name' not in kwargs or 'age' not in kwargs:
            print('用户名和年龄必须使用关键字的形式传值')
            return
        print(kwargs['name'])
        print(kwargs['age'])
    register(1, 2, name='liangjing', age=20)
    #liangjing
    # 20
    
    

    命名关键字形参:在函数定义阶段,*后面的参数都是命名关键字参数。

    特点:在传值时,必须按照key=value的方式传值,并且key必须命名关键字参数的指定的参数名。

    闭包函数:

    闭包函数是

    : 函数对象、函数嵌套、名称空间与作用域的结合体。

    注意:

    1.必须要在函数内定义
    - 2.可以引用外层函数的名字
    		def outer(x):
                def inner():
                    print(x)
                    pass
                return inner
            x = 10
            inner = outer(x)
            inner()
    
    

    闭包函数的作用

    - 闭包函数的作用:
    1.为了装饰器作准备的。
    2.减少代码冗余
    
    

    装饰器:

    1.什么是装饰器?

    在不修改被装饰对象的源代码与调用方式的前提下,为其添加新的功能。
    
    

    2.定义装饰器:

    - 不修改被装饰对象的源代码
    - 不修改被装饰对象的调用方式
    
    
    - 被装饰对象 ---》 需要添加新功能的  函数
                - 装饰器 ---> 为需要添加新功能的函数添加功能  函数
        # 模板
        		def wrapper(func):  # func函数对象 ---> 被装饰对象
                    # *args, **kwargs用于接收被装饰对象的参数
                    def inner(*args, **kwargs):
                        # 在调用被装饰对象前 添加新功能
                        res = func(*args, **kwargs)
    
                        # 在调用被装饰对象后 添加新功能
                        return res
                    return inner
    
    

    3.统计时间认证

    import time
    def download_movie():
    	print('开始下载')
    	time.sleep(5)
    	print('下载结束')
    	return 'cang老师.mp4'
    def time_record(func):
    	def inner(*args, **kwargs):
    		start_time = time.time()  # 获取当前时间戳
    		res = func(*args, **kwargs)  # func --> download_movie
    		end_time = time.time()
    		print(end_time - start_time)
    		return res
        return inner
    
    

    4.装饰器的语法糖

    语法糖是python内置的,可以引用所有的装饰器
    
    @: 就是语法糖
    
    - 如何使用:
    	@装饰器
         def 被装饰对象():
         	pass
    
    注意: 使用语法糖必须遵循,装饰器的定义必须要在被装饰对象之上。
    
    

    有参装饰器模板

    def user_info(user):
        def wrapper(func):
            def inner(*args,**kwargs):
                res = func(*args,**kwargs)
                return res
            return inner
        return wrapper
    
    

    无参装饰器模板

    def wrapper(func):
    	def inner(*args,**kwargs):
    		res = func(*args,**kwargs)
            # 在被装饰对象前调用添加功能
    		return res
    	return inner
    
    

    1.叠加装饰器

     1.叠加装饰器
            同一个被装饰对象可以叠加装饰多个装饰器
            装饰顺序:
                由下往上装饰
    
            执行顺序:
                由上往下执行
    
    

    2.有参装饰器

    本质上就是在无参装饰器上套了一个外层函数,
    无参装饰器可以引用外层函数的名字。
    
    应用:用户权限的认证
    
    

    无参装饰器与有参装饰器的使用

    @无参装饰器
    - @有参装饰器('参数1', '参数2')  ---》 调用有参装饰器会得到一个无参装饰器
    
    

    3.迭代器

    迭代

    迭代: 重复迭代的过程,每一次都是基于上一次的结果而来的。
    
    

    迭代器:

    迭代取值的工具。
    
    

    可迭代对象:

    凡是内部有__iter__()方法对象。
                list, str, tuple, dict, set, f
    
    

    获取迭代器:

    list1 = [1, 2, 3]
    # 调用__iter__()会得到一个返回值,该返回值是一个迭代器对象。
    iter_list = list1.__iter__()
    
    

    如何通过迭代器取值

    每一次调用__next__()都会从迭代器中取出一个值
    iter_list.__next__()
    注意: 取到最后一个时,若值没有,则会报错。
    
    

    捕获异常

    while True:
    	try:
    		print(iter_list.__next__())
    
    	except StopIteration:
    		break
    
    

    for循环原理

    # in: 会将可迭代对象自动调用__iter__()变成迭代器对象。
    for i in 可迭代对象:
    	# 会自定帮你调用__next__
         print(i)
    # for循环内部也会有一个捕获异常机制,一旦遇到异常也会停止取值。
    
    

    迭代器的优缺点:

    优点:
    1.提供了一种不依赖于索引的取值方式
    2.节省内存
    
    缺点:
    1.指定取某个值麻烦,每一次取值都要从第一个开始查找补充: 
    2.不能通过len计算长度
    
    

    .生成器

    生成的工具
    生成器是一个自定义的迭代器。
    
    

    yield:方法

    - yield必须在函数内部定义
    - yield可以保存函数的暂停状态
    yield的效果与return雷同
    
    生成器 ---》 生成器对象
    迭代器 ---》 迭代器对象
    
    凡是函数内部有yield,在调用函数时不会执行函数体代码,会返回一个生成器对象,本质上是一个迭代器。
    
    

    return与yield的区别:

    相同点:
        都可以返回无限制的值。
    
    不同点:
        yield可以返回多次值,return只能返回一次
        
    迭代器对象.__next__()  ==   next(迭代器对象)
    
    

    .面向过程编程

    核心是 “过程” 二字, 过程指的是解决问题的步骤,即先干什么再干什么。
    基于该编程思想编写程序,就好在设计一条流水线,一种机械式的思维方式。
    
    
     # 设计编写程序的步骤:
    注册功能: ----> 用户合法性的校验 ----> 拼接用户数据格式---->
    保存到文件中。
    
    

    优缺点

            优点:
                复杂的流程化,进而简单化
    
            缺点:
                牵一发而动全身,扩展性差
    
    
    

    .三元表达式

    成立返回的结果  if 判断条件 else 不成立返回的结果
    
    

    列表生成式

    - 生成一个列表
    # for循环了几次,列表中就有几个值
    l = [line for line in 可迭代对象]
    [任意的值 for line in 可迭代对象]
    print(l)  # list
    
    
    

    生成器生成式

    - 生成一个生成器对象 ---》 生成一个迭代器对象
    tuple = ()
    (line for line in 可迭代对象)
    g = (任意值 for line in 可迭代对象)
    print(g)  # 生成器对象
    
    

    列表生成式与生成器生成式的区别

            - 列表生成式
                优点:
                    可以依赖于索引取值,取值方便
    
                缺点:
                    在数据量过大时浪费资源
    
            - 生成器生成式
                优点:
                    在数据量过大时节省资源
    
                缺点:
                    不依赖于索引取值,取值麻烦。
    
    
    

    匿名函数

    匿名函数

    匿名函数:没有名字的函数:
                lambda x: x + x  # ---> 内存地址
                    # def (x):
                    #    return x + x
                名字 = lambda x: x + x
                名字()  # 匿名---》 有名  ---》 还不如直接通过def 来定义。
    
    

    有名字的函数:

    def 名字(x):  # 名字 ---> 内存地址
        pass
    
    

    注意

    函数名字 + ()调用,执行函数体代码
    
    匿名函数没有名字,不能单独使用。
    
    

    匿名的应用:

    配合内置函数一起使用。
    
    

    内置函数

    max: 获取可迭代对象中最大值
    min: 获取可迭代对象中最小值
    sorted: 对可迭代对象中的数据进行排序
       默认是: 升序
       reverse=True: 降序
    
    

    map,reduce,filter

    map: 映射
    map(函数地址, 可迭代对象)
    将可迭代对象中的值遍历取出,并且按照指定的规则映射出新的map对象。
    调用返回的是map对象。
    
    reduce: 合并
    reduce(函数地址, 可迭代对象, 初始值)
    将可迭代对象中的值两两合并,并且可以设置初始值
    return 合并后的值
    
    filter: 过滤
    filter(函数地址, 可迭代对象)
    将可迭代对象中的值遍历取出,然后通过判断,若条件成立 “过滤获取” 对应的值。
    并将获取的值放到一个filter对象中。
    return filter对象
    
    

    函数递归

    函数重复 “直接或间接” 调用函数本身,会进入死循环。
    
            缺点:
                1.毫无意义
                2.内存溢出
    
    
    有意义的递归:
    - 递推:
    指的是重复地执行, 每一次执行都要拿到一个更接近于结果的结果,
                    递推必要有一个终止条件。
    
    - 回溯:
    当递推找到一个终止条件后,开始一步一步往上回溯,最终得到一个结果。
    
                age(5) = age(4) + 2
                age(4) = age(3) + 2
                age(3) = age(2) + 2
                age(2) = age(1) + 2
                age(1) = 80
    
    
  • 相关阅读:
    2018年秋季个人阅读计划
    java当中JDBC当中JNDI用来查找dataSource的例子
    为什么要引入激活函数?
    为什么引入神经网络来做识别,判断,预测?
    给出一个生活中的最简单的两层神经网的实际例子
    MapReduce的输入文件是两个
    hadoop在eclipse当中如何添加源码?
    MapReduce的shuffle过程详解
    hadoop WordCount例子详解。
    Hadoop的eclipse的插件是怎么安装的?
  • 原文地址:https://www.cnblogs.com/WQ577098649/p/11947016.html
Copyright © 2020-2023  润新知