zoukankan      html  css  js  c++  java
  • 函数部分总结

    一、自定义函数

      一、函数概念

        1、什么是函数:函数就是封装一个功能。(程序中如果没有函数的引用,会产生重复代码多,可读性差的特点。)

        2、函数的定义:def 关键词开头,空格之后接函数名称和圆括号()

    l1 = [1,2,3,4]
    def my_len():
        # def 关键字 定义一个函数
        # my_len 函数名书写规则与变量一样
        # def与函数名中间一个空格
        # 函数名():加上冒号
        # 函数体
        count = 0
        for j in l1:
            count += 1
        print(count)
    my_len()
    l1 = [1,2,3,4]
    def my_len():
        count = 0
        for j in l1:
            count += 1
        return count
    print(my_len())
    # 函数的返回值:
    # 写函数,不要在函数中写print()
    # return
    # 1、在函数中,遇到return结束函数。
    # 2、将返回值给函数的调用者。
    #   无 return = return None
    #   return 1个值 该值是什么,就直接返回给函数的调用者,函数名()
    #   return 多个值,将多个值放到一个元组中,返回给函数的调用者。

      二、函数的传参   

        函数分为形参和实参:

        形参:形式参数,不代表实际的变量。

        实参:实际参数,带入形参中的变量。

        形参传参:1、位置传参。按顺序,一一对应。

                2、默认参数。传参则覆盖,不传则默认,默认参数永远在位置参数的后面。

        形参传参:1、位置传参。按顺序,一一对应。

               2、关键字传参,不按顺序,一一对应。

               3、混合传参,关键字参数永远在位置参数的后面。

        形参传递顺序:位置参数,*args,默认参数,**kwargs

    def test(a, *args, **kwargs):
        print(a)    # 1
        print(args) # (2, 3)
        print(kwargs)   # {'e': 5, 'd': '4'}
    test(1, 2, 3, d='4', e=5)
     
    # 1还是参数a的值,args表示剩余的值,kwargs在args之后表示成对键值对。
    # * 魔法运用
    def func(*args):
        print(args)
    l1 = [1,2,30]
    l2 = [1,2,33,21,45,66]
    tu = (1,2,3)
    func(1,2,30,1,2,33,21,45,66)    # (1, 2, 30, 1, 2, 33, 21, 45, 66)
    func(*'qweqrfdsaf') # ('q', 'w', 'e', 'q', 'r', 'f', 'd', 's', 'a', 'f')
    func(*{'name':'alex',"age":12}) # ('name', 'age')
    func(*l1,*l2)   # (1, 2, 30, 1, 2, 33, 21, 45, 66)
    def func(*args):
        print(args)
    func(1,2,3,10,20,80)    # (1, 2, 3, 10, 20, 80)
    def func(**kwargs):
        print(kwargs)
    dic1 = {'name1':'alex','age1':46}
    dic2 = {'name':'老男孩','age':56}
    func(**dic1,**dic2) # {'age1': 46, 'name1': 'alex', 'name': '老男孩', 'age': 56}
    # 在函数的调用执行时,
    #   *可迭代对象,代表打散(list,tuple,str,dict(键))将元素一一添加到args。
    #  **字典,代表打散,将所有键值对放到一个kwargs字典里。
    
    # 在函数定义时, *args,**kwargs代表的是聚合。
    def func(*args,**kwargs):
        print(args)
        print(kwargs)
    dic1 = {'name1':'alex','age1':46}
    dic2 = {'name':'老男孩','age':56}
    func(*[1,2,3,4],*'asdfsad',**dic1,**dic2)
    # (1, 2, 3, 4, 'a', 's', 'd', 'f', 's', 'a', 'd')
    # {'name': '老男孩', 'name1': 'alex', 'age': 56, 'age1': 46}

      三、函数有用信息

    def func1():
        """
        此函数是完成登陆的功能,参数分别是...作用。
        :return: 返回值是登陆成功与否(True,False)
        """
        print(666)
        return True
    func1() # 666
    print(func1.__name__)   # func1
    print(func1.__doc__)    # 显示注释内容

    二、命名空间和作用域

      一、命名空间

        命名空间的本质:存放名字与值的绑定关系   

        命名空间一共分为三种:

          全局命名空间:代码在运行伊始,创建的存储“变量名与值的关系”的空间

          局部命名空间:在函数的运行中开辟的临时的空间

          内置命名空间:存放了python解释器

        三种命名空间之间的加载与取值顺序:

        加载顺序:内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载)

        取值:在局部调用:局部命名空间->全局命名空间->内置命名空间

        在全局调用:全局命名空间->内置命名空间

      二、作用域

        作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域。

        全局作用域(globals):包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效

        局部作用域(locals):局部名称空间,只能在局部范围内生效

        global关键字

    #global
    # 1,在局部空间内,声明一个全局变量
    def func1():
        global name
        name = '老男孩'
        print(name) # 老男孩
    func1()
    print(name) # 老男孩
    # 2,在局部空间内改变一个全局变量
    a = 4
    def func1():
        global a    # 5
        a = 5
    func1()
    print(a)

        nolocal关键字

    #nonlocal
    # 1,不能修改全局变量。
    #在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,
    # 并且引用的哪层,从那层及以下此变量全部发生改变。
    a = 4
    def func1():
        b = 6
        def func2():
            b = 666
            print(b) # 666
        func2()
        print(b) # 6
    func1()
    
    b = 4
    def func1():
        b = 6
        def func2():
            nonlocal b
            b = 666
            print(b) # 666
        func2()
        print(b) # 666
    print(b)    # 4
    func1()

      三、函数名的应用

    # 函数名是函数的名字,本质:变量,特殊的变量。
    # 1,单独打印函数名  <function func1 at 0x0000000000872378>
    def func1():
        print(666)
    print(func1)  # <function func1 at 0x0000000000872378>
    a = 6
    print(a)    # 6
    # 2、函数名的赋值
    def func2():
        print(666)
    
    f = func2
    f() # 666
    # 3、函数名可以作为容器类数据的元素
    def f1():
        print(1211)
    def f2():
        print(1222)
    def f3():
        print(1233)
    def f4():
        print(1233)
    l1 = [f1, f2, f3, f4]
    for i in l1:
        i()
    # 4、函数名可以作为参数
    a = 1
    def f1(x):
        print(x)    # 1
    f1(a)
    def f1():
        print(666)
    def f2(x):  # x = f1
        x()  # f1()
    f2(f1)
    # 5、函数名可以作为函数的返回值
    def wraaper():
        def inner():
            print(666)
        return inner
    ret = wraaper()  # inner
    ret()  # inner()

    三、闭包和装饰器

      一、闭包

        闭包:就是内层函数对外层函数(非全局)变量的引用。

        闭包:当函数开始执行时,如果遇到闭包,他又一个机制,他会永远开辟一个内存空间,将闭包中的额变量等值放入其中,不会随着函数的执行完毕而消失。

        判断是不是闭包:内层函数名.__closure__ 结果是:cell...就是闭包

    name = '老男孩'
    def wraaper2(n):
        #  n = '老男孩'
        def inner():
            print(n)    # 老男孩
        inner()
        print(inner.__closure__)    # (<cell at 0x000001E3F9123B28: str object at 0x000001E3F9010F30>,)
    wraaper2(name)

      二、装饰器

        开放封闭原则:

        1、对扩展是开放的

        2、对修改是封闭的

        装饰器主要功能和装饰器固定结构:在不改变函数调用方式的基础上在函数的前、后添加功能。

        装饰器固定格式

    def timer(func):
        def inner(*args,**kwargs):
            '''执行函数之前要做的'''
            re = func(*args,**kwargs)
            '''执行函数之后要做的'''
            return re
        return inner

        带参数的装饰器

    def outer(flag):
        def timer(func):
            def inner(*args,**kwargs):
                if flag:
                    print('''执行函数之前要做的''')
                re = func(*args,**kwargs)
                if flag:
                    print('''执行函数之后要做的''')
                return re
            return inner
        return timer
    @outer(False)
    
    def func():
        print(111)
    
    func()

        多个装饰器装饰同一个函数

    def wrapper1(func):
        def inner():
            print('wrapper1 ,before func')  # 第二步
            func()
            print('wrapper1 ,after func')   # 第四步
        return inner
    
    def wrapper2(func):
        def inner():
            print('wrapper2 ,before func')  # 第一步
            func()
            print('wrapper2 ,after func')   # 第五步
        return inner
    
    @wrapper2
    @wrapper1
    def f():
        print('in f')   # 第三步
    f()

    四、迭代器和生成器

      一、迭代器

        可迭代协议:可以被迭代要满足的要求,可以将某个数据集内的数据“一个挨着一个的取出来”,就叫做迭代,内部实现了__iter__方法

        迭代协议:必须拥有__iter__方法和__next__方法

        迭代器的好处:

          1、节省内存空间。

          2、满足惰性机制。

          3、不能反复取值,不可逆。

         可迭代计算过程:

          1、将可迭代对象转化成迭代器

          2、内部使用__next__方法取值

          3、运用了异常处理去处理报错。    

    l2 = [1, 2, 3, 4, 5, 6, 7, 8]
    l2_obj = l2.__iter__()
    while True:
        try:
            i = l2_obj.__next__()
            print(i)
        except Exception:
            break

      二、生成器

        生成器:生成器本质上是迭代器。

        初始生成器:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行

        生成器函数定义:

          1、一个包含yield关键字的函数就是一个生成器函数

          2、next 和send 功能一样,都是执行一次,send获取下一个值可以给上一个yield赋值。

          使用send的注意事项:第一次使用生成器的时候,使用next获取下一个值,最后一个yield不能接受外部的值

    def generator():
        print(123)  # 123
        content = yield 1
        print(content)  # hello
        print(456)  #456
        yield 2
    g = generator()
    g.__next__()
    g.send('hello')

      三、列表推导式和生成器表达式

        1、列表推导式:用列表推导式能够构建的任何列表,用别的都可以构建,一目了然,占内存。

    l2 = [i*i for i in range(1,11)]
    print(l2)   # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

        2、生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表,不易看出,节省内存。

    l_obj = ('python%s期' % i for i in range(1,12))
    print(l_obj)    # <generator object <genexpr> at 0x000001AAF0AEBDB0>
    print(l_obj.__next__()) # python1期
    print(l_obj.__next__()) # python2期
    print(l_obj.__next__()) # python3期

        总结:

          1.把列表解析的[]换成()得到的就是生成器表达式

          2.列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存

          3.Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可 以直接这样计算一系列值的和:

    五、内置函数

        3.x版本python共提供68种内置函数

    详细内容见http://www.cnblogs.com/qiujie/p/8982773.html,内置函数思维导图:https://www.processon.com/view/link/5ae949b8e4b09b1bf63730c4

    六、匿名函数

        匿名函数:为了解决那些功能很简单的需求而设计的一句话函数。

    def calc(n):
        return n*n
    print(calc(10))
    
    cal = lambda n:n*n
    print(cal(10))

    上面是我们对calc这个匿名函数的分析,下面给出了一个关于匿名函数格式的说明

    函数名 = lambda 参数 :返回值
    
    #参数可以有多个,用逗号隔开
    #匿名函数不管逻辑多复杂,只能写一行,且逻辑执行结束后的内容就是返回值
    #返回值和正常的函数一样可以是任意数据类型

    我们可以看出,匿名函数并不是真的不能有名字。

      匿名函数的调用和正常的调用也没有什么分别。 就是 函数名(参数) 就可以了~~~

      匿名函数与内置函数举例:

    l=[3,2,100,999,213,1111,31121,333]
    print(max(l))
    
    dic={'k1':10,'k2':100,'k3':30}
    print(max(dic))
    print(dic[max(dic,key=lambda k:dic[k])])
    
    # 31121
    # k3
    # 100
    
    res = map(lambda x:x**2,[1,5,7,4,8])
    for i in res:
        print(i)
    
    # 1
    # 25
    # 49
    # 16
    # 64
    
    res = filter(lambda x:x>10,[5,8,11,9,15])
    for i in res:
        print(i)
        
    # 11
    # 15

    七、递归函数

        递归:一个函数在内部调用自己的函数称为递归,递归的次数在python是有限制的,默认递归次数是997次。

    # 输出斐波那契第n个数
    def fib(n):
        if n==1 or n==2:
            return 1
        return fib(n-1)+fib(n-2)

    函数部分思维导图:https://www.processon.com/view/link/5ae94a2be4b09b1bf637320e

  • 相关阅读:
    Codeforces Round #649 (Div. 2) D. Ehab's Last Corollary
    Educational Codeforces Round 89 (Rated for Div. 2) E. Two Arrays
    Educational Codeforces Round 89 (Rated for Div. 2) D. Two Divisors
    Codeforces Round #647 (Div. 2) E. Johnny and Grandmaster
    Codeforces Round #647 (Div. 2) F. Johnny and Megan's Necklace
    Codeforces Round #648 (Div. 2) G. Secure Password
    Codeforces Round #646 (Div. 2) F. Rotating Substrings
    C++STL常见用法
    各类学习慕课(不定期更新
    高阶等差数列
  • 原文地址:https://www.cnblogs.com/qiujie/p/8977972.html
Copyright © 2011-2022 走看看