全栈测试 一 | py3基础 二 : 函数练习和强化

函数基础


 1. 速查笔记

#-- 函数相关的语句和表达式  
    myfunc('spam')                     # 函数调用  
    def myfunc():                      # 函数定义  
    return None                        # 函数返回值  
    global a                           # 全局变量  
    nonlocal x                         # 在函数或其他作用域中使用外层(非全局)变量  
    yield x                            # 生成器函数返回  
    lambda                             # 匿名函数  

2. 函数的好处

代码复用、保持代码一致性、可扩展性

函数的参数


1. 速查笔记

#-- 函数参数,不可变参数通过“值”传递,可变参数通过“引用”传递  
    def f(a, b, c): print(a, b, c)  
    f(1, 2, 3)                                   # 参数位置匹配  
    f(1, c = 3, b = 2)                           # 参数关键字匹配  
    def f(a, b = 1, c = 2): print(a, b, c)  
    f(1)                                         # 默认参数匹配  
    f(1, 2)                                      # 默认参数匹配  
    f(a = 1, c = 3)                              # 关键字参数和默认参数的混合  
    # Keyword-Only参数:出现在*args之后 必须用关键字进行匹配  
    def keyOnly(a, *b, c): print('')             # c就为keyword-only匹配 必须使用关键字c = value匹配  
    def keyOnly(a, *, b, c): ......              # b c为keyword-only匹配 必须使用关键字匹配  
    def keyOnly(a, *, b = 1): ......             # b有默认值 或者省略 或者使用关键字参数b = value  
  
#-- 可变参数匹配: * 和 **  
    def f(*args): print(args)                    # 在元组中收集不匹配的位置参数  
    f(1, 2, 3)                                   # 输出(1, 2, 3)  
    def f(**args): print(args)                   # 在字典中收集不匹配的关键字参数  
    f(a = 1, b = 2)                              # 输出{'a':1, 'b':2}  
    def f(a, *b **c): print(a, b, c)             # 两者混合使用  
    f(1, 2, 3, x = 4, y = 5)                     # 输出1, (2, 3), {'x':4, 'y':5}  

示例:

# -*-  coding:utf-8 -*-
def canshu(a,*args,**kwargs):
    print('位置参数值a: %s '%a)
    print(args)
    print(kwargs)
    #函数默认的返回值个数为0时,返回None,如果返回值个数为一个,那么就是return后的值,如果返回值个数大于1,以元组形式返回
    #return后的语句,不会再执行
    return 0
 
test= canshu('python','ruby','java',c = 'shell',d = 'perl')
print(test)

运行结果:

位置参数值a: python 
('ruby', 'java')
{'c': 'shell', 'd': 'perl'}
0

2. 参数的其他知识点

#-- 函数调用时的参数解包: * 和 ** 分别解包元组和字典  
    func(1, *(2, 3))  <==>  func(1, 2, 3)  
    func(1, **{'c':3, 'b':2})  <==>  func(1, b = 2, c = 3)  
    func(1, *(2, 3), **{'c':3, 'b':2})  <==>  func(1, 2, 3, b = 2, c = 3)  
      
#-- 函数属性:(自己定义的)函数可以添加属性  
    def func():.....  
    func.count = 1                      # 自定义函数添加属性  
    print.count = 1                     # Error 内置函数不可以添加属性  
      
#-- 函数注解: 编写在def头部行 主要用于说明参数范围、参数类型、返回值类型等  
    def func(a:'spam', b:(1, 10), c:float) -> int :  
        print(a, b, c)  
    func.__annotations__                # {'c':<class 'float'>, 'b':(1, 10), 'a':'spam', 'return':<class 'int'>}  
    # 编写注解的同时 还是可以使用函数默认值 并且注解的位置位于=号的前边  
    def func(a:'spam'='a', b:(1, 10)=2, c:float=3) -> int :  
        print(a, b, c)  

函数的局部变量与全局变量-作用域


1. 速查笔记

#-- Python函数变量名解析:LEGB原则,即:  
    """ 
    local(functin) --> encloseing(相邻的) function locals --> global(module) --> build-in(python) 
    说明:以下边的函数maker为例 则相对于action而言 X为Local N为Encloseing 
    """  
  
#-- 嵌套函数举例:工厂函数  
    def maker(N):  
        def action(X):  
            return X ** N  
        return action  
    f = maker(2)                       # pass 2 to N  
    f(3)                               # 9, pass 3 to X  
  
#-- 嵌套函数举例:lambda实例  
    def maker(N):  
        action = (lambda X: X**N)  
        return action  
    f = maker(2)                       # pass 2 to N  
    f(3)                               # 9, pass 3 to X  
  
#-- nonlocal和global语句的区别  
    # nonlocal应用于一个嵌套的函数的作用域中的一个名称 例如:  
    start = 100  
    def tester(start):  
        def nested(label):  
            nonlocal start             # 指定start为tester函数内的local变量 而不是global变量start  
            print(label, start)  
            start += 3  
        return nested  
    # global为全局的变量 即def之外的变量  
    def tester(start):  
        def nested(label):  
            global start               # 指定start为global变量start  
            print(label, start)  
            start += 3  
        return nested 

2.全局变量的作用域是整个函数,局部变量作用域是定义该变量的子程序

递归函数


定义:在函数内部,可以调用其他函数,如果一个函数在内部调用自身,就是递归函数

特性:① 必须有一个明确的结束条件;② 每一次更深的递归时,问题规模相比上次递归应减少

简单示例:裴波那契数列

def fibo(n):
    if n<3:
        return 1
    return fibo(n-2)+fibo(n-1)
 
print(fibo(5))

 匿名函数lambda


 1. 速查笔记 

#-- 匿名函数:lambda  
    f = lambda x, y, z : x + y + z      # 普通匿名函数,使用方法f(1, 2, 3)  
    f = lambda x = 1, y = 1: x + y      # 带默认参数的lambda函数  
    def action(x):                      # 嵌套lambda函数  
        return (lambda y : x + y)  
    f = lambda: a if xxx() else b       # 无参数的lambda函数,使用方法f()  
  
#-- lambda函数与map filter reduce函数的结合  
    list(map((lambda x: x + 1), [1, 2, 3]))              # [2, 3, 4]  
    list(filter((lambda x: x > 0), range(-4, 5)))        # [1, 2, 3, 4]  
    functools.reduce((lambda x, y: x + y), [1, 2, 3])    # 6  
    functools.reduce((lambda x, y: x * y), [2, 3, 4])    # 24  

装饰器


1.速查笔记

#-- 函数装饰器:是它后边的函数的运行时的声明 由@符号以及后边紧跟的"元函数"(metafunction)组成  
        @staticmethod  
        def smeth(x): print(x)  
    # 等同于:  
        def smeth(x): print(x)  
        smeth = staticmethod(smeth)  

定义:在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)

经典示例:

# -*-  coding:utf-8 -*-
import time
def timer(func): #把被装饰的函数ceshi的内存地址传给了func
    def deco(*args,**kwargs):
        start_time = time.time()
        func(*args,**kwargs)
        stop_time = time.time()
        print('测试函数运行时间',(stop_time-start_time))
    return deco #返回deco的内存地址
 
@timer
def ceshi(a):
    time.sleep(3)
    print('测试%s'%a)
ceshi('装饰器')

2. 原则:①不能修改被装饰函数的源代码;②不能修改被装饰函数的调用方式

3.实现装饰器的技能储备

① 函数本身即是变量

② 高阶函数,把一个函数名当做实参穿给另一个函数

③ 嵌套函数

生成器


1.速查笔记

#-- 生成器函数:yield VS return  
    def gensquare(N):  
        for i in range(N):  
            yield i** 2                 # 状态挂起 可以恢复到此时的状态  
    for i in gensquare(5):              # 使用方法  
        print(i, end = ' ')             # [0, 1, 4, 9, 16]  
    x = gensquare(2)                    # x是一个生成对象  
    next(x)                             # 等同于x.__next__() 返回0  
    next(x)                             # 等同于x.__next__() 返回1  
    next(x)                             # 等同于x.__next__() 抛出异常StopIteration  
      
#-- 生成器表达式:小括号进行列表解析  
    G = (x ** 2 for x in range(3))      # 使用小括号可以创建所需结果的生成器generator object  
    next(G), next(G), next(G)           # 和上述中的生成器函数的返回值一致  
    #(1)生成器(生成器函数/生成器表达式)是单个迭代对象  
    G = (x ** 2 for x in range(4))  
    I1 = iter(G)                        # 这里实际上iter(G) = G  
    next(I1)                            # 输出0  
    next(G)                             # 输出1  
    next(I1)                            # 输出4  
    #(2)生成器不保留迭代后的结果  
    gen = (i for i in range(4))  
in gen                            # 返回True  
in gen                            # 返回True  
in gen                            # 返回False,其实检测2的时候,1已经就不在生成器中了,即1已经被迭代过了,同理2、3也不在了  

2. 生成器表达式

局限性:只能适合简单的算法

示例: 

test = (x**2 for x in range(1,10))
print(next(test))
print(test.__next__())

3. 生成器函数 yield

斐波那契函数的打印示例:

def fib(max):
    a,b,n = 1,1,0
    while n<max:
        yield b
        a,b = b,a+b
        n+=1
    return b
test = fib(10)
print(test.__next__())
print(next(test))
for i in test:
    print(i)
原文地址:https://www.cnblogs.com/wuzhiming/p/13347828.html