• 使用doctest单元测试方式培训讲解:Python函数基础


    # coding = utf-8
    
    '''
    函数声明:
    def name([arg,... arg = value,... *arg, **kwarg]):
        suite
    
    1. 当编译器遇到 def,会生成创建函数对象指令。
       也就是说 def 是执⾏行指令,⽽不仅仅是个语法关键字。
       可以在任何地⽅方动态创建函数对象。
    2. 可以使用默认参数、可变参数和关键字参数
            arg = value 是默认参数
            *args是可变参数,args接收的是一个tuple;
            **kwargs是关键字参数,kwargs接收的是一个dict。
    
    lambda函数
    不同于⽤用 def 定义复杂函数,lambda 只能是有返回值的简单的表达式。使⽤用赋值语句会引发语法 错误,可以考虑⽤用函数代替。
    '''
    
    '''
    *****************************************************
    1. 函数创建
       函数是第一类对象,可作为其他函数的实参或返回值。
       函数总是有返回值。就算没有 return,默认也会返回 None。
    *****************************************************
    '''
    def test1(name):
        '''
    
        >>> test1('a').__name__ # 查看函数返回函数的名字
        'a'
    
        >>> test1('b').__name__ # 查看函数返回函数的名字
        'b'
    
        >>> test1('a')()        # 调用函数返回的函数
        call function a
    
        >>> print(test1('c'))   # 调用函数,返回2个值:整型和字符串
        (0, 'test')
        '''
        if name == "a":
            def a():
                print('call function a')
            return a
        elif name == "b":
            def b(): pass
            return b
        else:
            return 0, 'test'
    
    '''
    *************************************************************
    2. 参数
       2.1 函数的传参方式灵活多变,可按位置顺序传参,也可不关⼼顺序⽤命名实参。
    *************************************************************
    '''
    def test21(a, b):
        '''
    
        >>> test21(1,2)      # 位置参数
        1 2
    
        >>> test21(b=3,a=4)  # 命名参数
        4 3
        '''
        print(a, b)
    
    '''
    *************************************************************
       2.2 ⽀持参数默认值。不过要⼩⼼,
           默认值对象在创建函数时生成,所有调用都使⽤同⼀对象。
           如果该默认值是可变类型,那么就如同 C 静态局部变量。
    *************************************************************
    '''
    def test22(x, lst=[]):
        '''
        >>> test22(1)
        [1]
    
        >>> test22(2)   # 保持了上次调⽤用状态。
        [1, 2]
    
        >>> test22(3, [])   # 显式提供实参,不使⽤用默认值。
        [3]
    
        >>> test22(3)   # 再次使⽤用默认值,会继续使用默认的列表对象
        [1, 2, 3]
    
        '''
    
        lst.append(x)
        return lst
    
    '''
    *************************************************************
       2.3 默认参数后⾯不能有其他位置参数,除非是变参。
       SyntaxError: def test23(a, b=1, c): pass
    
       2.4 用 *args 收集 "多余" 的位置参数,**kwargs 收集 "额外" 的命名参数。
           这两个名字只是惯例,可 ⾃自由命名。
           *args是可变参数,args接收的是一个tuple;
           **kwargs是关键字参数,kwargs接收的是一个dict。
    *************************************************************
    '''
    def test24(a, b=1, *args, **kwargs):
        '''
    
        >>> test24(0)
        0
        1
        ()
        {}
    
        >>> test24(0,2,3,4)
        0
        2
        (3, 4)
        {}
    
        >>> test24(0,2,3,4,x=5)
        0
        2
        (3, 4)
        {'x': 5}
    
        # 可 "展开" 序列类型和字典,将全部元素当做多个实参使⽤用。如不展开的话,那仅是单个实参对象。
        >>> test24(*range(5), **{'x': 10, 'y': 11})
        0
        1
        (2, 3, 4)
        {'x': 10, 'y': 11}
    
        >>> test24(range(5))
        range(0, 5)
        1
        ()
        {}
    
        # 单个 "*" 展开序列类型,或者仅是字典的主键列表。
        # "**" 展开字典键值对。但如果没有变参收集, 展开后多余的参数将引发异常。
        >>> p = dict(a=20,b=21)
    
        >>> test24(p)
        {'a': 20, 'b': 21}
        1
        ()
        {}
    
        >>> test24(*p)  # 仅展开 keys(),test("a"、"b")
        a
        b
        ()
        {}
    
        >>> test24(**p)  # 展开 items(),test(a = 1, b = 2)。
        20
        21
        ()
        {}
        '''
    
        print(a)
        print(b)
        print(args)
        print(kwargs)
    
    '''
    *************************************************************
    3. 作用域
       3.1 函数形参和内部变量都存储在 locals 名字空间中。
    *************************************************************
    '''
    def test31(a, b=1):
        '''
    
        >>> test31(100)
        {'s': 'Hello Python', 'b': 1, 'a': 100}
    
        '''
    
        s = 'Hello Python'
        print(locals())
    
    '''
    *************************************************************
        3.2 除⾮使用 global、nonlocal 特别声明,
          否则,在函数内部使用赋值语句,总是在 locals 名字空间中 新建一个对象关联。
          注意:"赋值" 是指名字指向新的对象,⽽⾮通过名字改变对象状态。
    
          名字查找顺序: locals -> enclosing function -> globals -> __builtins__
        • locals: 函数内部名字空间,包括局部变量和形参。
        • enclosing function: 外部嵌套函数的名字空间。
        • globals: 函数定义所在模块的名字空间。
        • __builtins__: 内置模块的名字空间。
    
          如果不修改全局变量也可以不使用global关键字。
          Python3 提供了 nonlocal 关键字,用来修改外部 嵌套函数名字空间, python2.7 没有。
          nonlocal关键字用来在函数或其他作用域中使用外层(非全局)变量。
    *************************************************************
    '''
    x, y = 1, 2  # 在模块级别直接定义的全局变量
    
    def test321():
        global x    # 引用全局变量
        x = 11
        y = 21      # 这里的 y 是局部变量
        global z    # 在函数内部定义一个全局变量,而没有在模块级别定义
        z = 3
    
        print(' in test321(): x=%d; y=%d; z=%d' % (x, y, z))
    
    def test322():
        print(' in test322(): x=%d; y=%d ; z=%d' % (x, y, z))    # 直接访问所有全局变量,包括变量z
    
    # 测试
    print('        out 1: x=%d; y=%d;  z=undefine' % (x, y))
    test321()
    test322()
    print('        out 2: x=%d; y=%d ; z=%d' % (x, y, z))
    
    
    '''
    *************************************************************
    3.3 闭包
        闭包(closure)是函数式编程的重要的语法结构。
        闭包也是一种组织代码的结构,它同样提高了代码的可重复使用性。
    *************************************************************
    '''
    
    def lineConfig(a,b):
        '''
        这个例子中,函数line与环境变量a,b构 成闭包。
        在创建闭包的时候,我们通过line_conf的参数a,b说明了这两个环境变量的取值,
        这样我们就确定了函数的最终形式(y = x + 1和y = 4x + 5)。
        我们只需要变换参数a,b,就可以获得不同的直线表达函数。
        由此,我们可以看到,闭包也具有提高代码可复用性的作用。
    
        >>> y1 = lineConfig(1, 1)   # 定义直线 y = x + 1
        >>> p1 = y1(2)              # 计算y坐标,获取x=2时y1的值
        >>> print(p1)
        3
    
        >>> lstPoint = [y1(x) for x in range(3)] # 计算y坐标列表
        >>> print(lstPoint)
        [1, 2, 3]
    
        >>> y2 = lineConfig(4, 5)   # 定义直线 y = 4x + 5
        >>> p2 = y2(x=2)            # 计算y坐标,获取x=2时y2的值
        >>> print(p2)
        13
        '''
    
        def line(x):
            return a*x + b
    
        return line
    
    
    def newCounter(i=0):
        '''
        两个独立的计数器
        >>> c1 = newCounter()
        >>> c2 = newCounter(2)
        >>> print(c1(),c1(),c1())
        1 2 3
    
        >>> print(c2(),c2(),c2())
        3 4 5
    
        '''
    
        def counter():
            nonlocal i
            i = i + 1
            return i
        return counter
    
    if __name__ == '__main__':
        import doctest
        doctest.testmod(verbose=True)
    

      

  • 相关阅读:
    解决RuntimeError: cuda runtime error (30) : unknown error at /pytorch/aten/src/THC/THCGeneral.cpp:70&NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the late
    查看Ubuntu/Anaconda/cuda/cudnn/Tensorflow/Pytorch版本
    创建新用户
    142. Linked List Cycle II
    网页版Instagram如何发照片
    141. Linked List Cycle
    将博客搬至CSDN
    92. Reverse Linked List II
    Dlib使用过程全记录(一)
    定制new和delete
  • 原文地址:https://www.cnblogs.com/atsats/p/7747552.html
Copyright © 2020-2023  润新知