zoukankan      html  css  js  c++  java
  • 装饰器,迭代器,生成器分析

    装饰器

    什么是装饰器

    装饰器本身可以是任意可调用的对象=>函数
    被装饰的对象也可以是任意可调用的对象=>函数

    一个装饰器是一个需要另一个函数作为参数的函数。在装饰器内部动态定义一个函数:wrapper(原意:包装纸)。这个函数将被包装在原始函数的四周,因此就可以在原始函数之前和之后执行一些代码.

    为何要用装饰器

    开放封闭原则: 软件一旦上线就应该对修改封闭,对扩展开放
    对修改封闭:
    1. 不能修改功能的源代码
    2. 也不能修改功能的调用方式

    对扩展开发     可以为原有的功能添加新的功能

    装饰器就是要在不修改功能源代码以及调用方式的前提下为原功能添加额外新的功能

    无参装饰器

    def outter(func):
        def wrapper(*args,**kwargs):
           res=func(*args,**kwargs)
           return res
        return wrapper  

    简单装饰器

    import time
    
    def index():
        print('welcome to index page')
        time.sleep(3)
        return 123
    
    def home(name):
        print('welcome %s to home page' %name)
        time.sleep(1)
    
    def outter(func):
        # func=最原始那个home的内地址
        def wrapper(*args,**kwargs):
            start=time.time()
            res=func(*args,**kwargs)
            stop=time.time()
            print('run time is %s' %(stop-start))
            return res
        return wrapper
    
    index=outter(index) #index=outter(最原始那个index的内地址) #index=wrapper函数的内地址
    home=outter(home) #index=outter(最原始那个home的内地址) #home=wrapper函数的内地址
    
    
    home('egon') #wrapper('egon')
    index() #wrapper()
    '''
    welcome egon to home page
    run time is 1.0155680179595947
    welcome to index page
    run time is 3.015437364578247
    '''

    装饰器的语法糖

    @装饰器的名字:要在被装饰对象正上方单独一行写上
    import time
    def timmer(func): # func=最原始那个home的内地址
        def wrapper(*args,**kwargs):
            start=time.time()
            res=func(*args,**kwargs)
            stop=time.time()
            print('run time is %s' %(stop-start))
            return res
        wrapper.__doc__=func.__doc__
        wrapper.__name__=func.__name__
        return wrapper
    
    @timmer #index=timmer(index) ##index=timmer(最原始那个index的内地址) #index=wrapper函数的内地址
    def index():
        """这是index功能"""
        print('welcome to index page')
        time.sleep(3)
        return 123
    
    @timmer #home=timmer(home) #index=timmer(最原始那个home的内地址) #home=wrapper函数的内地址
    def home(name):
        """这是home功能"""
        print('welcome %s to home page' %name)
        time.sleep(1)
    
    # home('egon') #wrapper('egon')
    # index() #wrapper()
    
    # print(help(index))
    # print(help(home))
    # print(index.__doc__)
    
    print(index.__name__)
    '''
    
    from functools import wraps
    
    import time
    def timmer(func): # func=最原始那个home的内地址
        @wraps(func)
        def wrapper(*args,**kwargs):
            start=time.time()
            res=func(*args,**kwargs)
            stop=time.time()
            print('run time is %s' %(stop-start))
            return res
        return wrapper
    
    @timmer
    def index():
        """这是index功能"""
        print('welcome to index page')
        time.sleep(3)
        return 123
    
    @timmer
    def home(name):
        """这是home功能"""
        print('welcome %s to home page' %name)
        time.sleep(1)
    
    print(help(index))
    print(index.__name__)
    装饰器的语法糖

    有参装饰器

    我们通过闭包知道参数可以嵌套函数里实现隐藏,并且实现全局参数的功能,与函数一起绑定

    #参数默认为空字符串
    def title(show=''):
        def printStar(func):
            def f(a,b):
                print(show,"*************************")
                return func(a,b)
            return f
        return printStar
    
    @title('add')
    def add(a,b):
        return a+b
    
    @title()
    def sub(a,b):
        return a-b
    
    print(add(1,1))
    print(sub(2,1))
    '''
    add *************************
    2
     *************************
    1
    '''
    def outter2(xxx,yyy):
        def outter(func):
            def wrapper(*args,**kwargs):
                res=func(*args,**kwargs)
                print(xxx)
                print(yyy)
                return res
            return wrapper
        return outter
    
    import time
    
    user_info={'current_user':None}
    
    def auth2(engine='file'):
        def auth(func):
            def wrapper(*args,**kwargs):
                if user_info['current_user'] is not None:
                    res=func(*args,**kwargs)
                    return res
                inp_user=input('username>>>: ').strip()
                inp_pwd=input('password>>>: ').strip()
    
                if engine == 'file':
                    print('基于文件的认证')
                    if inp_user == 'egon' and inp_pwd == '123':
                        # 记录登录状态
                        user_info['current_user']=inp_user
    
                        print('login successful')
                        res=func(*args,**kwargs)
                        return res
                    else:
                        print('user or password error')
                elif engine == 'mysql':
                    print('基于mysql数据的认证')
                
                '''
                elif engine == 'ldap':
                    print('基于ldap的认证')
                else:
                    print('无法识别认证源')
                '''
            return wrapper
        return auth
    
    @auth2(engine='mysql') # @auth ===> index=auth(最原始那个index的内存地址)===》index=wrapper
    def index():
        """这是index功能"""
        print('welcome to index page')
        time.sleep(2)
        return 123
    
    @auth2(engine='file')
    def home(name):
        """这是home功能"""
        print('welcome %s to home page' %name)
        time.sleep(1)
    
    index() #wrapper()
    home('joek')
    更加复杂一些的有参装饰器

    这时我们可以发现函数传送参数是修改def f(a, b),就是第三层的函数

    叠加多个装饰器

    当一个被装饰的对象同时叠加多个装饰器时

    装饰器的加载顺序是:自下而上

    装饰器内wrapper函数的执行顺序是:自上而下     忘记的话可以借助pycharm的断点分析,看一下加载与执行

    import time
    
    def timmer(func): #func=wrapper2的内存地址
        def wrapper1(*args, **kwargs):
            print('===================================>wrapper1运行了')
            start=time.time()
            res = func(*args, **kwargs) #===========================>跳到wrapper2去执行了,
            stop=time.time()
            print('run time is %s' %(stop - start))
            return res
        return wrapper1
    
    def auth(engine='file'):
        def xxx(func): # func=最原始那个index的内存地址
            def wrapper2(*args, **kwargs):
                print('===================================>wrapper2运行了')
                name=input('username>>>: ').strip()
                pwd=input('password>>>: ').strip()
                if engine == 'file':
                    print('基于文件的认证')
                    if name == 'egon' and pwd  == '123':
                        print('login successfull')
                        res = func(*args, **kwargs)
                        return res
                elif engine == 'mysql':
                    print('基于mysql的认证')
                elif engine == 'ldap':
                    print('基于ldap的认证')
                else:
                    print('错误的认证源')
            return wrapper2
        return xxx
    
    @timmer # index=timmer(wrapper2的内存地址) #index=wrapper1的内存地址
    @auth(engine='file') #@xxx #index=xxx(最原始那个index的内存地址) #index=wrapper2的内存地址
    def index():
        print('welcome to index page')
        time.sleep(2)
    
    index() #wrapper1的内存地址()
    '''
    
    
    
    @auth(engine='file')    #装饰器的顺序不一样结果不一样,上一个的运行时间包含了
    @timmer                     #另外一个装饰器的运行时间
    def index():
       print('welcome to index page')
       time.sleep(2)
    
    index() #wrapper1的内存地址()
    多装饰器分析

    迭代器

    什么是迭代器

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

    li=['a','b','c','d','e']
    li=('a','b','c','d','e')
    li='hello'
    
    i=0
    while i < len(li):
       print(li[i])
       i+=1
    View Code

    迭代器指的是迭代取值的工具,该工具的特点是可以不依赖于索引取值

    为何要用迭代器

    为了找出一种通用的&可以不依赖于索引的迭代取值方式

    如何用迭代器

    可迭代的对象:但凡内置有.__iter__方法的对象都称之为可迭代的对象
    迭代器对象:既内置有__iter__方法,又内置有__next__方法

    关于__iter__方法:
    调用可迭代对象的__iter__会的到一个迭代器对象
    调用迭代器对象的__iter__会的到迭代器本身

    总结迭代器的优缺点

    优点:
    1. 提供了一种通用的&可以不依赖于索引的迭代取值方式
    2. 同一时刻在内存中只有一个值,更加节省内存

    缺点:
    1. 取指定值不如索引灵活,并且迭代器是一次性的
    2. 无法预知迭代器数据的个数

    可迭代的对象:    序列str,list,tuple     字典dict    集合set与文件对象
    迭代器对象: 文件对象

    事实上iter函数与__iter__方法联系非常紧密,iter()是直接调用该对象的__iter__(),并把__iter__()的返回结果作为自己的返回值,故该用法常被称为“创建迭代器”。

    dic={'x':1,'y':2,'z':3}
    
    iter_dic=dic.__iter__()      #把字典转化成迭代器
    print(iter_dic)
      res1=iter_dic.__next__()
    print(res1)
      res2=iter_dic.__next__()
    print(res2)
      res3=iter_dic.__next__()
    print(res3)
      res4=iter_dic.__next__()
    print(res4)
    例子

    文件也是可迭代对象

    iter_dic=open(r'F:python学习代码fb_user_name.txt',mode='rt',encoding='utf-8')
    
    while True:
      try:               #try用来捕捉异常,使程序可以正常进行下去
        print(iter_dic.__next__())
      except StopIteration:
        break
    View Code

    for准确地说应该是迭代器循环,for循环的原理如下:
    1. 先调用in后面那个值的__iter__方法,得到迭代器对象
    2. 执行迭代器.__next__()方法得到一个返回值,然后赋值给一个变量k,运行循环体代码
    3. 循环往复,直到迭代器取值完毕抛出异常然后捕捉异常自动结束循环

    dic={'x':1,'y':2,'z':3}
    iter_dic=dic.__iter__()
    print(iter_dic)
    print(iter_dic.__iter__())
    
    for k in dic: #iter_dic=dic.__iter__()
      print(k)
    
    
    with open(r'db.txt',mode='rt',encoding='utf-8') as f:
      for line in f: #iter_f=f.__iter__()
    print(line)
    View Code

    自定义迭代器

    yield关键字:只能用在函数内
    在函数内但凡包含有yield关键字,再去执行函数,就不会立刻运行函数体代码了
    会得到一个返回值,该返回值成之为生成器对象,生成器本质就是迭代器

    总结yield:
      1. 提供一种自定义迭代器的解决方案
      2. yield可用于返回值

    yield VS return
    相同点:都可以用于返回值
    不同点:yield可以暂停函数,yield可以返回多次值,而return只能返回值一次值函数就立刻终止

    def func():
        print('=====>第一次')
        yield 1
        print('=====>第二次 ')
        yield 2
        print('=====>第三次')
        yield 3
        print('=====>第四次')
    

      

    def my_range(start,stop,step=1):
        while start < stop:
            yield start
            start+=step
    
    res=my_range(1,5,2) # 1 3
    
    next(res)
    next(res)
    # print(next(res))
    #StopIteration
    for item in res:
      print(item)
    '''
    1
    3
    '''
    
    for item in my_range(1,5,2):
        print(item)
    '''
    1
    3
    '''

    迭代期间不能修改被迭代的对象

    在python中,for循环相当于一个迭代器(Iterator),在循环体中改变循环变量的值对循环次数是没有影响的。
    迭代器在一个独立的线程中工作,并且拥有一个mutex互斥锁。迭代器被创建的时候,建立了一个内存索引表(单链表),这个索引表指向原来的对象,当原来的对象数量改变的时候,这个索引表的内容没有同步改变,所以当索引指针往下移动的时候,便找不到要迭代的对象,于是产生错误。就是说迭代器在工作的时候,是不允许被迭代的对象被改变的。

    import time
    print("when we use 'for':",time.ctime())
    for i in range(10):
        print('i:',i)
        for j in range(i+1,10):
            print('	j=',j)
            if i+j<5:
                j=j+1
                continue
            else:
                i=j      #在这一步,从实际结果来看i的值并没有被修改,这一步完全没有执行
                break
    print("over':",time.ctime())
    '''
    when we use 'for': Wed Nov 14 20:24:08 2018
    i: 0
        j= 1
        j= 2
        j= 3
        j= 4
        j= 5
    i: 1
        j= 2
        j= 3
        j= 4
    i: 2
        j= 3
    i: 3
        j= 4
    i: 4
        j= 5
    i: 5
        j= 6
    i: 6
        j= 7
    i: 7
        j= 8
    i: 8
        j= 9
    i: 9
    over': Wed Nov 14 20:24:08 2018
    '''

    从运行结果可以看出,i并没有变动

    List、Set等是动态的、可变对象数量的数据结构,但是迭代器是单向不可变、只能顺序读取、不能逆序操作的数据结构,当迭代器指向的原始数据发生变化时,迭代器自己就迷失了方向。因此,我们可以改用while循环

    import time
    print("
    when we use 'while':",time.ctime())
    i=0
    while i < 10:
        print('i:',i)
        j=i+1
        while j < 10:
            print('	j=',j)
            if i+j<5:
                j=j+1
                continue
            else:
                i=j
                break
        i=i+1
    print("over':",time.ctime())
    '''
    when we use 'while': Wed Nov 14 20:26:08 2018
    i: 0
        j= 1
        j= 2
        j= 3
        j= 4
        j= 5
    i: 6
        j= 7
    i: 8
        j= 9
    over': Wed Nov 14 20:26:08 2018
    '''
    View Code

    此时就得到了我们想要的效果

    需要注意的是,while循环的运行效率比for循环低,所以会花费较多的时间,在数值非常大时才能体现出来

    在for循环中直接更改列表中元素的值不会起作用

    l = list(range(10)[::2])
    
    print (l)
    
    for n in l:
    
        n = 0
    
    print (l)
    View Code

    运行结果:

    [0, 2, 4, 6, 8]
    [0, 2, 4, 6, 8]

    l中的元素并没有被修改

    在for循环中更改list值的方法

    使用range

    l = list(range(10)[::2])
    
    print (l)
    
    for i in range(len(l)):
    
        l[i] = 0
    
    print (l)
    
    '''运行结果
    [0, 2, 4, 6, 8]
    [0, 0, 0, 0, 0]
    '''
    View Code

    使用enumerate

    l = list(range(10)[::2])
    
    print (l)
    
    for index,value in enumerate(l):
    
        l[index] = 0
    
    print (l)
    
    '''运行结果
    [0, 2, 4, 6, 8]
    [0, 0, 0, 0, 0]
    '''
    View Code

    生成器

    由于生成器自动实现了迭代器协议,而迭代器协议对很多人来说,也是一个较为抽象的概念。所以,为了更好的理解生成器,我们需要简单的回顾一下迭代器协议的概念。迭代器协议是指:对象需要提供next方法,它要么返回迭代中的下一项,要么就引起一个Stoplteration异常,以终止迭代可迭代对象就是:实现了迭代器协议的对象协议是一种约定,可迭代对象实现迭代器协议,Python的内置工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象。为什么在Python中,文件还可以使用for循环进行遍历呢?这是因为,在Python中,文件对象实现了迭代器协议,for循环并不知道它遍历的是一个文件对象,它只管使用迭代器协议访问对象即可。正是由于Python的文件对象实现了迭代器协议,我们才得以使用如此方便的方式访问文件Python使用生成器对延迟操作提供了支持。所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果。这也是生成器的主要好处。

    Python有两种不同的方式提供生成器:生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如,sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样计算一系列值的和:语法上和函数类似:生成器函数和常规函数几乎是一样的。它们都是使用def语句进行定义,差别在于,生成器使用yield语句返回一个值,而常规函数使用return语句返回一个值自动实现迭代器协议:对于生成器,Python会自动实现迭代器协议,以便应用到迭代背景中(如for循环,sum函数)。由于生成器自动实现了迭代器协议,所以,我们可以调用它的next方法,并且,在没有值可以返回的时候,生成器自动产生Stoplteration异常状态挂起:生成器使用yield语句返回一个值。yield语句挂起该生成器函数的状态,保留足够的信息,以便之后从它离开的地方继续执行使用生成器以后,代码行数更少。不使用生成器的时候,对于每次结果,我们首先看到的是result.append(index),其次,才是index。也就是说,我们每次看到的是一个列表的append操作,只是append的是我们想要的结果。使用生成器的时候,直接yield index,少了列表append操作的干扰,我们一眼就能够看出,代码是要返回index。这个例子充分说明了,合理使用生成器,能够有效提高代码可读性。只要大家完全接受了生成器的概念,理解了yield语句和return语句一样,也是返回一个值。那么,就能够理解为什么使用生成器比不使用生成器要好,能够理解使用生成器真的可以让代码变得清晰易懂。

    我们知道的迭代器有两种:一种是调用方法直接返回的,一种是可迭代对象通过执行iter方法得到的,迭代器有的好处是可以节省内存。
    如果在某些情况下,我们也需要节省内存,就只能自己写。我们自己写的这个能实现迭代器功能的东西就叫生成器。
     
    Python中提供的生成器:
    1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行
    2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表
     
    生成器Generator:
    本质:迭代器(所以自带了__iter__方法和__next__方法,不需要我们去实现)
    特点:惰性运算,开发者自定义
     
    一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。
    import time
    def genrator_fun1():
        a = 1
        print('现在定义了a变量')
        yield a
        b = 2
        print('现在又定义了b变量')
        yield b
    g1 = genrator_fun1()
    print('g1 : ',g1)       #打印g1可以发现g1就是一个生成器
    print('-'*20)   #我是华丽的分割线
    print(next(g1))
    time.sleep(1)   #sleep一秒看清执行过程
    print(next(g1))
    View Code

    生成器有什么好处呢?就是不会一下子在内存中生成太多数据

    生成器监听文件输入的例子
    import time
    
    def tail(filename):
        f = open(filename)
        f.seek(0, 2) #从文件末尾算起
        while True:
            line = f.readline()  # 读取文件中新的文本行
            if not line:
                time.sleep(0.1)
                continue
            yield line
    tail_g = tail('tmp')
    for line in tail_g:
        print(line)
    View Code

     seed

    def generator():
        print(123)
        content = yield 1
        print('=======',content)
        print(456)
        yield
    g = generator()
    ret = g.__next__()
    print('***',ret)
    ret = g.send('hello')   #send的效果和next一样
    print('***',ret)
    '''
    123
    *** 1
    ======= hello
    456
    *** None
    '''

    send 获取下一个值的效果和next基本一致只是在获取下一个值的时候,给上一yield的位置传递一个数据
    使用send的注意事项
    第一次使用生成器的时候 是用next获取下一个值
    最后一个yield不能接受外部的值

    计算移动平均值

    def averager():
        total = 0.0
        count = 0
        average = None
        while True:
            term = yield average
            total += term
            count += 1
            average = total/count
    View Code

    计算移动平均值(2)_预激协程的装饰器   

    def init(func):  #在调用被装饰生成器函数的时候首先用next激活生成器
        def inner(*args,**kwargs):
            g = func(*args,**kwargs)
            next(g)
            return g
        return inner
    @init
    def averager():
        total = 0.0
        count = 0
        average = None
        while True:
            term = yield average
            total += term
            count += 1
            average = total/count
    
    g_avg = averager()
    # next(g_avg)   在装饰器中执行了next方法
    print(g_avg.send(10))
    print(g_avg.send(30))
    print(g_avg.send(5))
    View Code

    这两个例子都出自于流畅的pathon

    yield from

    def gen1():
        for c in 'AB':
            yield c
        for i in range(3):
            yield i
    print(list(gen1()))
    
    def gen2():
        yield from 'AB'
        yield from range(3)
    print(list(gen2()))
    
    '''
    ['A', 'B', 0, 1, 2]
    ['A', 'B', 0, 1, 2]
    
    '''

    生成器与列表解析的区别

    生成器表达式来源于迭代和列表解析的组合,生成器和列表解析类似,但是它使用尖括号而不是方括号
    
    # 列表解析生成列表
    [ x ** 3 for x in range(5)]
    [0, 1, 8, 27, 64]
    
    # 生成器表达式
    (x ** 3 for x in range(5))
    <generator object <genexpr> at 0x000000000315F678>
    # 两者之间转换
    list(x ** 3 for x in range(5))
    [0, 1, 8, 27, 64]

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

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

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

    sum(x ** 2 for x in range(4))

    而不用多此一举的先构造一个列表:

    sum([x ** 2 for x in range(4)]) 

    三元表达式(实际上是类似三元表达式的if表达式)

    def max2(x,y):
     if x > y:
        return x
     else:
        return y
    
    x=10
    y=20
    res='条件成立的值' if x > y else '条件不成立的值'
    print(res)
    
    也可以用简单的公式,如下,
    a = 1
    b = 2
    h = ''
    h = a-b if a>b else a+b
    print(h)
    
    s="ok"
    s2="tzc"
    v="yes" if s=="ok" else ("yes" if s2=="tzc" else "no")
    print(v)
    #yes

    列表生成式

    语法    [要放入列表的数据 简单的表达式1 表达式2]

    #列表生成式是快速生成一个列表的一些公式
    numbers = []
    for x in range(0,101):
        numbers.append(x)
    print(numbers)
    
    #x for x in range(0,101)   for循环遍历出来的值,放入列表中
    numbers =[x for x in range(0,101)]
    print(numbers)

    自定义输出的格式

    l=[]
    for i in range(1,11):
      if i > 4:
        res='egg%s' %i
        l.append(res)
    
    print(l)
    
    l=['egg%s' %i for i in range(1,11) if i > 4]
    print(l)
    '''
    ['egg5', 'egg6', 'egg7', 'egg8', 'egg9', 'egg10']
    ['egg5', 'egg6', 'egg7', 'egg8', 'egg9', 'egg10']
    '''

    筛选出需要的,也就是加上条件

    names=['egon','lxx','yyx','cw','alex','wxx']
    l=[]
    for name in names:
      if name != 'egon':
        res='%s_DSB' %name
        l.append(res)
    
    print(l)
    
    l=['%s_DSB' %name for name in names if name != 'egon']
    print(l)
    

      

    #普通双重for循环
    list7 =[]
    for x in range(0,10):
        for y in range(10,20):
            s = x*y
            list7.append(s)
    print(list7)
    #支持双重for循环
    list3 = [x*y for x in range(0,10) for y in range(10,20)]print(list3)
    双重for循环
    列表生成器和列表生成式的区别
    
    list6 = [x for x in range(10)]
    print(list6)
    #generator列表生成器#生成的是一个对象,不会把数据直接创建出来,当for遍历的时候,生成器对象会调用next()函数,获取下一个要生成的数据
    generator = (x for x in range(10))
    #生成式对象可以调用next()函数获取下一个要生成的数字,如果next()函数没有获取到下一个数据,会抛出异常StopIteration ,程序出错
    #生成式对象可以使用for遍历,使用next()不停的获取下一个数据,如果没有下一个数据循环结束
    for x in generator:
        print(x)
    列表生成器与列表生成式的区别

    字典生成式

    items=[('name','egon'),('age',18),('sex','male')]
    
    dic={}
    for k,v in items:
      dic[k]=v
    print(dic)
    
    res={k:v for k,v in items if k != 'sex'}
    print(res)
    
    res={i for i in 'hello'}
    print(res)
    '''
    {'name': 'egon', 'age': 18, 'sex': 'male'}
    {'name': 'egon', 'age': 18}
    {'e', 'h', 'l', 'o'}
    '''
    

      

  • 相关阅读:
    Struts2中ModelDriven的使用
    Android 如何让 app 自行处理 power key M
    url后面带斜杠与不带斜杠的区别
    Http Request Method:options
    org.springframework.boot.builder.SpringApplicationBuilder.<init>
    Uncaught (in promise) DOMException: Failed to execute 'open' on 'XMLHttpRequest': Invalid URL
    git将多个commit合并成一个
    idea error:Command line is too long
    java使用zxing插件绘制二维码
    git解决冲突插件之Beyond Compare
  • 原文地址:https://www.cnblogs.com/596014054-yangdongsheng/p/9712405.html
Copyright © 2011-2022 走看看