zoukankan      html  css  js  c++  java
  • 函数

    一、高阶函数

    高阶函数定义:
    1.函数接收的参数是一个函数名
    2.函数的返回值是一个函数名
    3.满足上述条件任意一个,都可称之为高阶函数
    import time
    def foo():
        print('你好啊林师傅')
    
    def test(func):
        print(func)
    
    test(foo)

    二、函数嵌套

    def father(auth_type):
        def son():
            def grandson():
                print('我的爷爷是%s' %auth_type)
            grandson()
        son()
    
    father('filedb')

    三、装饰器(装饰器=高阶函数+函数嵌套+闭包)

    普通装饰器

    import time
    def timmer(func): #func=test
        def wrapper():
            # print(func)
            start_time=time.time()
            func() #就是在运行test()
            stop_time = time.time()
            print('运行时间是%s' %(stop_time-start_time))
        return wrapper
    
    @timmer #test=timmer(test)
    def test():
        time.sleep(3)
        print('test函数运行完毕')
    test()

    带参数装饰器

    import time
    def timmer(func): #func=test1
        def wrapper(*args,**kwargs): 
            start_time=time.time()
            func(*args,**kwargs) 
            stop_time = time.time()
            print('运行时间是%s' %(stop_time-start_time))
            return wrapper
    
    @timmer #test=timmer(test)
    def test(name,age):
        time.sleep(3)
        print('test函数运行完毕,名字是【%s】 年龄是【%s】' %(name,age))
        

    当被修饰函数有返回值的情况

    import time
    def timmer(func): #func=test1
        def wrapper(*args,**kwargs): 
            start_time=time.time()
            res=func(*args,**kwargs) # 接收返回值
            stop_time = time.time()
            print('运行时间是%s' %(stop_time-start_time))
            return res # 返回
        return wrapper
    
    @timmer #test=timmer(test)
    def test(name,age):
        time.sleep(3)
        print('test函数运行完毕,名字是【%s】 年龄是【%s】' %(name,age))
        return '这是test的返回值'

    装饰器带参数的情况(装饰函数外面在套一层函数还接收变量)

    user_list=[
        {'name':'alex','passwd':'123'},
        {'name':'linhaifeng','passwd':'123'},
        {'name':'wupeiqi','passwd':'123'},
        {'name':'yuanhao','passwd':'123'},
    ]
    current_dic={'username':None,'login':False}
    
    def auth(auth_type='filedb'):
        def auth_func(func):
            def wrapper(*args,**kwargs):
                print('认证类型是',auth_type)
                if auth_type == 'filedb':
                    if current_dic['username'] and current_dic['login']:
                        res = func(*args, **kwargs)
                        return res
                    username=input('用户名:').strip()
                    passwd=input('密码:').strip()
                    for user_dic in user_list:
                        if username == user_dic['name'] and passwd == user_dic['passwd']:
                            current_dic['username']=username
                            current_dic['login']=True
                            res = func(*args, **kwargs)
                            return res
                    else:
                        print('用户名或者密码错误')
                elif auth_type == 'ldap':
                    print('鬼才特么会玩')
                    res = func(*args, **kwargs)
                    return res
                else:
                    print('鬼才知道你用的什么认证方式')
                    res = func(*args, **kwargs)
                    return res
    
            return wrapper
        return auth_func
    
    @auth(auth_type='filedb') #auth_func=auth(auth_type='filedb')-->@auth_func 附加了一个auth_type  --->index=auth_func(index)
    def index():
        print('欢迎来到京东主页')
    
    @auth(auth_type='ldap')
    def home(name):
        print('欢迎回家%s' %name)
    #
    @auth(auth_type='sssssss')
    def shopping_car(name):
        print('%s的购物车里有[%s,%s,%s]' %(name,'奶茶','妹妹','娃娃'))

    四、迭代器和生成器

    为何要有迭代器?什么是可迭代对象?什么是迭代器对象?

    #1、为何要有迭代器?
    对于序列类型:字符串、列表、元组,我们可以使用索引的方式迭代取出其包含的元素。但对于字典、集合、文件等类型是没有索引的,若还想取出其内部包含的元素,则必须找出一种不依赖于索引的迭代方式,这就是迭代器
    
    #2、什么是可迭代对象?
    可迭代对象指的是内置有__iter__方法的对象,即obj.__iter__,如下
    'hello'.__iter__
    (1,2,3).__iter__
    [1,2,3].__iter__
    {'a':1}.__iter__
    {'a','b'}.__iter__
    open('a.txt').__iter__
    
    #3、什么是迭代器对象?
    可迭代对象执行obj.__iter__()得到的结果就是迭代器对象
    而迭代器对象指的是即内置有__iter__又内置有__next__方法的对象
    
    文件类型是迭代器对象
    open('a.txt').__iter__()
    open('a.txt').__next__()
    
    
    #4、注意:
    迭代器对象一定是可迭代对象,而可迭代对象不一定是迭代器对象
    View Code

    如何使一个对象可以被for循环----->变为迭代器对象---->how? 1、有__iter__方法;2、__iter__方法返回一个迭代器;

    class Foo(object):
        def __iter__(self):
            return iter([11, 22, 33])
        
        #def __iter__(self):
        #   yield 1
        #    yield 2
        #    yield 3
    
    obj = Foo()
    for i in obj:
        print(i)

    迭代器对象的使用

    dic={'a':1,'b':2,'c':3}
    iter_dic=dic.__iter__() #得到迭代器对象,迭代器对象即有__iter__又有__next__,但是:迭代器.__iter__()得到的仍然是迭代器本身
    iter_dic.__iter__() is iter_dic #True
    
    print(iter_dic.__next__()) #等同于next(iter_dic)
    print(iter_dic.__next__()) #等同于next(iter_dic)
    print(iter_dic.__next__()) #等同于next(iter_dic)
    # print(iter_dic.__next__()) #抛出异常StopIteration,或者说结束标志
    
    #有了迭代器,我们就可以不依赖索引迭代取值了
    iter_dic=dic.__iter__()
    while 1:
        try:
            k=next(iter_dic)
            print(dic[k])
        except StopIteration:
            break
            
    #这么写太丑陋了,需要我们自己捕捉异常,控制next,python这么牛逼,能不能帮我解决呢?能,请看for循环
    View Code

    for循环

    #基于for循环,我们可以完全不再依赖索引去取值了
    dic={'a':1,'b':2,'c':3}
    for k in dic:
        print(dic[k])
    
    #for循环的工作原理
    #1:执行in后对象的dic.__iter__()方法,得到一个迭代器对象iter_dic
    #2: 执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码
    #3: 重复过程2,直到捕捉到异常StopIteration,结束循环

     生成器表达式

    #1、把列表推导式的[]换成()就是生成器表达式
    
    #2、示例:生一筐鸡蛋变成给你一只老母鸡,用的时候就下蛋,这也是生成器的特性
    >>> chicken=('鸡蛋%s' %i for i in range(5))
    >>> chicken
    <generator object <genexpr> at 0x10143f200>
    >>> next(chicken)
    '鸡蛋0'
    >>> list(chicken) #因chicken可迭代,因而可以转成列表
    ['鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4',]
    
    #3、优点:省内存,一次只产生一个值在内存中
    View Code
    def test():
        for i in range(4):
            yield i
    t=test()
    
    t1=(i for i in t)
    t2=(i for i in t1)
    print(list(t1))
    print(list(t2))  # 打印出空列表。生成器只有在运行的时候才真正执行。故一开始定义t1、t2两个生成器根本不会执行,当执行“print(list(t1))”时,生成器t1被list迭代完,故t2不会执行,注意不是报错

    五、函数作用域

    #1、作用域即范围
            - 全局范围(内置名称空间与全局名称空间属于该范围):全局存活,全局有效
          - 局部范围(局部名称空间属于该范围):临时存活,局部有效
    #2、作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关,如下
    x=1
    def f1():
        def f2():
            print(x)
        return f2
    x=100
    def f3(func):
        x=2
        func()
    x=10000
    f3(f1())
    
    #3、查看作用域:globals(),locals()
    
    
    LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
    locals 是函数内的名字空间,包括局部变量和形参
    enclosing 外部嵌套函数的名字空间(闭包中常见)
    globals 全局变量,函数定义所在模块的名字空间
    builtins 内置模块的名字空间

    六、闭包

    闭包的意义与应用

    #闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
    #应用领域:延迟计算(原来我们是传参,现在我们是包起来)
        from urllib.request import urlopen
    
        def index(url):
            def get():
                return urlopen(url).read()
            return get
    
        baidu=index('http://www.baidu.com')
        print(baidu().decode('utf-8'))

    七、递归

    1. 必须有一个明确的结束条件
    2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
    3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

    递归调用应该分为两个明确的阶段:递推,回溯 

    #1、递归调用应该包含两个明确的阶段:回溯,递推
        回溯就是从外向里一层一层递归调用下去,
            回溯阶段必须要有一个明确地结束条件,每进入下一次递归时,问题的规模都应该有所减少(否则,单纯地重复调用自身是毫无意义的)
    
        递推就是从里向外一层一层结束递归
    
    #2、示例+图解。。。
    # salary(5)=salary(4)+300
    # salary(4)=salary(3)+300
    # salary(3)=salary(2)+300
    # salary(2)=salary(1)+300
    # salary(1)=100
    #
    # salary(n)=salary(n-1)+300     n>1
    # salary(1) =100                n=1
    
    def salary(n):
        if n == 1:
            return 100
        return salary(n-1)+300
    
    print(salary(5))
    View Code
  • 相关阅读:
    iptables操作指令
    最怕问初衷,大梦成空
    kettle官网wiki
    Pentaho Spoon (Kettle) 出现 Timestamp :Unable to get timestamp from resultset at index 30 错误的解决
    win10安装vs2013失败解决方法
    2020 最新 kail 安装教程
    01_docker学习笔记(一)
    数据结构的基础概念
    BOS3
    配置文件添加druid控制台
  • 原文地址:https://www.cnblogs.com/linyuhong/p/10212107.html
Copyright © 2011-2022 走看看