zoukankan      html  css  js  c++  java
  • Python04-函数基础2-迭代器、生成器、面向过程编程、三元表达式等

    一 迭代器

    二 生成器

    三 面向过程编程

    四 三元表达式、列表推导式、生成器表达式

    五 递归与二分法

    六 匿名函数

    七 内置函数

    八 阶段性练习

    九 作业

     

    一 迭代器

    一 迭代的概念

    #迭代器即迭代的工具,那什么是迭代呢?
    #迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值
    while True: #只是单纯地重复,因而不是迭代
        print('===>') 
        
    l=[1,2,3]
    count=0
    while count < len(l): #迭代
        print(l[count])
        count+=1

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

    #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、注意:
    迭代器对象一定是可迭代对象,而可迭代对象不一定是迭代器对象

    三 迭代器对象的使用

    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循环

    四 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,结束循环

    五 迭代器的优缺点

    #优点:
      - 提供一种统一的、不依赖于索引的迭代方式
      - 惰性计算,节省内存
    #缺点:
      - 无法获取长度(只有在next完毕才知道到底有几个值)
      - 一次性的,只能往后走,不能往前退

    二 生成器

    一 什么是生成器

    #只要函数内部包含有yield关键字,那么函数名()的到的结果就是生成器,并且不会执行函数内部代码
    
    def func():
        print('====>first')
        yield 1
        print('====>second')
        yield 2
        print('====>third')
        yield 3
        print('====>end')
    
    g=func()
    print(g) #<generator object func at 0x0000000002184360>

    二 生成表达式yield

    #yield的功能:
    #1、yield为我们提供了一种自定义迭代器对象的方法
    #2、yield与return的区别1:yield可以返回多次值 #2:函数暂停与再继续的状态是由yield帮我们保存的
    
    #
    会抛异常的 def eater(name): print ("%s is ready to eat"%name) food=yield print ("%s is eating %s"%(name,food)) g=eater("alex") g.send(None)#####next(g) g.send("shit") #不会抛异常的 def eater(name): print ("%s is ready to eat"%name) while True: ############不断传值 food=yield print ("%s is eating %s"%(name,food)) g=eater("alex") #首先初始化 g.send(None)#####next(g) #然后e.send:1 从暂停的位置将值传给yield 2、与next一样(有顺序的) g.send("bones")

    生成器就是迭代器

    g.__iter__
    g.__next__
    #2、所以生成器就是迭代器,因此可以这么取值
    res=next(g)
    print(res)

    四 练习

    1、自定义函数模拟range(1,7,2)

    2、模拟管道,实现功能:tail -f access.log | grep '404'

    #用一个生成器写
    import time
    #####tail功能
    def tail(filepath):
        with open(filepath,"rb") as f:
            f.seek(0,2)
            while True:
                line=f.readline()
                if line:
                    yield line
                else:
                    time.sleep(0.01)
    ####grep功能
    def grep(lines,pattern):
        for i in lines:
            i=i.decode("utf-8")
            if pattern in i:
                print(i,end="")
    
    lines=grep(tail("a.txt"),"404")
    用一个生成器写tail -f a.txt |grep 404
    #用两个生成器写tail -f a.txt |grep 404
    import time
    #####tail功能
    def tail(filepath):
        with open(filepath,"rb") as f:
            f.seek(0,2)
            while True:
                line=f.readline()
                if line:
                    yield line
                else:
                    time.sleep(0.01)
    ####grep功能
    def grep(lines,pattern):
        for i in lines:
            i=i.decode("utf-8")
            if pattern in i:
                yield i
                
    lines=grep(tail("a.txt"),"404")
    for line in lines:
        print (line,end="")
    用两个生成器写tail -f a.txt |grep 404
    #题目一:
    def my_range(start,stop,step=1):
        while start < stop:
            yield start
            start+=step
    
    #执行函数得到生成器,本质就是迭代器
    obj=my_range(1,7,2) #1  3  5
    print(next(obj))
    print(next(obj))
    print(next(obj))
    print(next(obj)) #StopIteration
    
    #应用于for循环
    for i in my_range(1,7,2):
        print(i)
    
    #题目二
    import time
    def tail(filepath):
        with open(filepath,'rb') as f:
            f.seek(0,2)
            while True:
                line=f.readline()
                if line:
                    yield line
                else:
                    time.sleep(0.2)
    
    def grep(pattern,lines):
        for line in lines:
            line=line.decode('utf-8')
            if pattern in line:
                yield line
    
    for line in grep('404',tail('access.log')):
        print(line,end='')
    
    #测试
    with open('access.log','a',encoding='utf-8') as f:
        f.write('出错啦404
    ')

    五 协程函数

    了解:协程与yield

    #yield关键字的另外一种使用形式:表达式形式的yield
    def eater(name):
        print('%s 准备开始吃饭啦' %name)
        food_list=[]
        while True:
            food=yield food_list
            print('%s 吃了 %s' % (name,food))
            food_list.append(food)
    
    g=eater('egon')
    g.send(None) #对于表达式形式的yield,在使用时,第一次必须传None,g.send(None)等同于next(g)
    g.send('蒸羊羔')
    g.send('蒸鹿茸')
    g.send('蒸熊掌')
    g.send('烧素鸭')
    g.close()
    g.send('烧素鹅')
    g.send('烧鹿尾')

    六 练习
    1、编写装饰器,实现初始化协程函数的功能

    2、实现功能:grep  -rl  'python'  /etc

    #题目一:
    def init(func):
        def wrapper(*args,**kwargs):
            g=func(*args,**kwargs)
            next(g)
            return g
        return wrapper
    @init
    def eater(name):
        print('%s 准备开始吃饭啦' %name)
        food_list=[]
        while True:
            food=yield food_list
            print('%s 吃了 %s' % (name,food))
            food_list.append(food)
    
    g=eater('egon')
    g.send('蒸羊羔')
    
    #题目二:
    #注意:target.send(...)在拿到target的返回值后才算执行结束
    import os
    def init(func):
        def wrapper(*args,**kwargs):
            g=func(*args,**kwargs)
            next(g)
            return g
        return wrapper
    
    @init
    def search(target):
        while True:
            filepath=yield
            g=os.walk(filepath)
            for dirname,_,files in g:
                for file in files:
                    abs_path=r'%s\%s' %(dirname,file)
                    target.send(abs_path)
    @init
    def opener(target):
        while True:
            abs_path=yield
            with open(abs_path,'rb') as f:
                target.send((f,abs_path))
    @init
    def cat(target):
        while True:
            f,abs_path=yield
            for line in f:
                res=target.send((line,abs_path))
                if res:
                    break
    @init
    def grep(pattern,target):
        tag=False
        while True:
            line,abs_path=yield tag
            tag=False
            if pattern.encode('utf-8') in line:
                target.send(abs_path)
                tag=True
    @init
    def printer():
        while True:
            abs_path=yield
            print(abs_path)
    
    
    g=search(opener(cat(grep('你好',printer()))))
    # g.send(r'E:CMSaaadb')
    g=search(opener(cat(grep('python',printer()))))
    g.send(r'E:CMSaaadb')
    View Code

    七 yield总结

    #1、把函数做成迭代器
    #2、对比return,可以返回多次值,可以挂起/保存函数的运行状态

    三 面向过程编程

    #1、首先强调:面向过程编程绝对不是用函数编程这么简单,面向过程是一种编程思路、思想,而编程思路是不依赖于具体的语言或语法的。言外之意是即使我们不依赖于函数,也可以基于面向过程的思想编写程序
    
    #2、定义
    面向过程的核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么
    
    基于面向过程设计程序就好比在设计一条流水线,是一种机械式的思维方式
    
    #3、优点:复杂的问题流程化,进而简单化
    
    #4、缺点:可扩展性差,修改流水线的任意一个阶段,都会牵一发而动全身
    
    #5、应用:扩展性要求不高的场景,典型案例如linux内核,git,httpd
    
    #6、举例
    流水线1:
    用户输入用户名、密码--->用户验证--->欢迎界面
    
    流水线2:
    用户输入sql--->sql解析--->执行功能

    ps:函数的参数传入,是函数吃进去的食物,而函数return的返回值,是函数拉出来的结果,面向过程的思路就是,把程序的执行当做一串首尾相连的功能,该功能可以是函数的形式,然后一个函数吃,拉出的东西给另外一个函数吃,另外一个函数吃了再继续拉给下一个函数吃。。。

    #grep -rl 'python' /etc
    #补充:os.walk
    # import os
    # g=os.walk(r'D:videopython20期day4a')
    # # print(next(g))
    # # print(next(g))
    # # print(next(g))
    # # print(next(g))
    # for pardir,_,files in g:
    #     for file in files:
    #         abs_path=r'%s\%s' %(pardir,file)
    #         print(abs_path)
    
    
    #分析二:[有小bug]
    # 第一步:拿到一个文件夹下所有的文件的绝对路径
    import os
    def init(func):
        def inner(*args,**kwargs):
            g=func(*args,**kwargs)
            next(g)
            return g
        return inner
    
    
    @init
    def search(target):  # r'D:videopython20期day4a'
        while True:
            filepath = yield
            g = os.walk(filepath)
            for pardir, _, files in g:
                for file in files:
                    abs_path = r'%s\%s' % (pardir, file)
                    #把abs_path传给下一个阶段
                    target.send(abs_path)
    
    # 第二步:打开文件拿到文件对象f
    @init
    def opener(target):
        while True:
            abs_path = yield
            with open(abs_path,'rb') as f:
                #把(abs_path,f)传给下一个阶段
                target.send((abs_path,f))
    
    #第三步:读取f的每一行内容
    @init
    def cat(target):
        while True:
            abs_path,f=yield
            for line in f:
                #把(abs_path,line)传给下一个阶段
                target.send((abs_path,line))
    
    #第四步:判断'python' in line
    @init
    def grep(target,pattern):
        pattern = pattern.encode('utf-8')
        while True:
            abs_path,line=yield
            if pattern in line:
                #把abs_path传给下一个阶段
                target.send(abs_path)
    
    #第五步:打印文件路径
    @init
    def printer():
        while True:
            abs_path=yield
            print('<%s>' %abs_path)
    
    g=search(opener(cat(grep(printer(),'python')))) #'python' in b'xxxxx'
    g.send(r'D:videopython20期day4a')
    grep -rl 'python' /etc[有小bug]
    #分析二:
    # 第一步:拿到一个文件夹下所有的文件的绝对路径
    import os
    def init(func):
        def inner(*args,**kwargs):
            g=func(*args,**kwargs)
            next(g)
            return g
        return inner
    
    @init
    def search(target):  # r'D:videopython20期day4a'
        while True:
            filepath = yield
            g = os.walk(filepath)
            for pardir, _, files in g:
                for file in files:
                    abs_path = r'%s\%s' % (pardir, file)
                    #把abs_path传给下一个阶段
                    target.send(abs_path)
    
    # 第二步:打开文件拿到文件对象f
    @init
    def opener(target):
        while True:
            abs_path = yield
            with open(abs_path,'rb') as f:
                #把(abs_path,f)传给下一个阶段
                target.send((abs_path,f))
    
    #第三步:读取f的每一行内容
    @init
    def cat(target):
        while True:
            abs_path,f=yield
            for line in f:
                #把(abs_path,line)传给下一个阶段
                res=target.send((abs_path,line))
                #满足某种条件,break掉for循环
                if res:
                    break
    
    #第四步:判断'python' in line
    @init
    def grep(target,pattern):
        pattern = pattern.encode('utf-8')
        res=False
        while True:
            abs_path,line=yield res
            res=False
            if pattern in line:
                #把abs_path传给下一个阶段
                res=True
                target.send(abs_path)
    
    #第五步:打印文件路径
    @init
    def printer():
        while True:
            abs_path=yield
            print('<%s>' %abs_path)
    
    g=search(opener(cat(grep(printer(),'python')))) #'python' in b'xxxxx'
    g.send(r'D:videopython20期day4a')
    
    
    
    #面向过程编程:核心是过程二字,过程指的就是解决问题的步骤,即先干什么后干什么。。。。
    #基于该思路编写程序就好比设计一条流水线,是一种机械式的思维方式
    
    #优点:复杂的问题流程化、进而简单化
    #缺点:可扩展性差
    grep -rl 'python' /etc

    四 三元表达式、列表推导式、生成器表达式

    一 三元表达式

    name=input('姓名>>: ')
    res='SB' if name == 'alex' else 'NB'
    print(res)

    二 列表推导式

    #1、示例
    egg_list=[]
    for i in range(10):
        egg_list.append('鸡蛋%s' %i)
    
    egg_list=['鸡蛋%s' %i for i in range(10)]
    
    #2、语法
    [expression for item1 in iterable1 if condition1
    for item2 in iterable2 if condition2
    ...
    for itemN in iterableN if conditionN
    ]
    类似于
    res=[]
    for item1 in iterable1:
        if condition1:
            for item2 in iterable2:
                if condition2
                    ...
                    for itemN in iterableN:
                        if conditionN:
                            res.append(expression)
    
    #3、优点:方便,改变了编程习惯,可称之为声明式编程
    i=[i for i in range(1,10,1) if i % 4 ==0]
    print (i)
    # [4, 8]

    三 生成器表达式

    #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、优点:省内存,一次只产生一个值在内存中

    四 声明式编程练习题

    1、将names=['egon','alex_sb','wupeiqi','yuanhao']中的名字全部变大写

    2、将names=['egon','alex_sb','wupeiqi','yuanhao']中以sb结尾的名字过滤掉,然后保存剩下的名字长度

    3、求文件a.txt中最长的行的长度(长度按字符个数算,需要使用max函数)

    4、求文件a.txt中总共包含的字符个数?思考为何在第一次之后的n次sum求和得到的结果为0?(需要使用sum函数)

    5、思考题

    with open('a.txt') as f:
        g=(len(line) for line in f)
    print(sum(g)) #为何报错?

    6、文件shopping.txt内容如下

    mac,20000,3
    lenovo,3000,10
    tesla,1000000,10
    chicken,200,1

    求总共花了多少钱?

    打印出所有商品的信息,格式为[{'name':'xxx','price':333,'count':3},...]

    求单价大于10000的商品信息,格式同上

    #题目一
    names=['egon','alex_sb','wupeiqi','yuanhao']
    names=[name.upper() for name in names]
    
    #题目二
    names=['egon','alex_sb','wupeiqi','yuanhao']
    names=[len(name) for name in names if not name.endswith('sb')]
    
    #题目三
    with open('a.txt',encoding='utf-8') as f:
        print(max(len(line) for line in f))
    
    #题目四
    with open('a.txt', encoding='utf-8') as f:
        print(sum(len(line) for line in f))
        print(sum(len(line) for line in f)) #求包换换行符在内的文件所有的字符数,为何得到的值为0?
        print(sum(len(line) for line in f)) #求包换换行符在内的文件所有的字符数,为何得到的值为0?
    
    #题目五(略)
    
    #题目六:每次必须重新打开文件或seek到文件开头,因为迭代完一次就结束了
    with open('a.txt',encoding='utf-8') as f:
        info=[line.split() for line in f]
        cost=sum(float(unit_price)*int(count) for _,unit_price,count in info)
        print(cost)
    
    
    with open('a.txt',encoding='utf-8') as f:
        info=[{
            'name': line.split()[0],
            'price': float(line.split()[1]),
            'count': int(line.split()[2]),
        } for line in f]
        print(info)
    
    
    with open('a.txt',encoding='utf-8') as f:
        info=[{
            'name': line.split()[0],
            'price': float(line.split()[1]),
            'count': int(line.split()[2]),
        } for line in f if float(line.split()[1]) > 10000]
        print(info)
    View Code

    五 递归与二分法

    一 递归调用的定义

    #递归调用是函数嵌套调用的一种特殊形式,函数在调用时,直接或间接调用了自身,就是递归调用

    二 递归分为两个阶段:递推,回溯

    #图解。。。
    # 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))

    三 python中的递归效率低且没有尾递归优化

    #python中的递归
    python中的递归效率低,需要在进入下一次递归时保留当前的状态,在其他语言中可以有解决方法:尾递归优化,即在函数的最后一步(而非最后一行)调用自己,尾递归优化:http://egon09.blog.51cto.com/9161406/1842475
    但是python又没有尾递归,且对递归层级做了限制
    
    #总结递归的使用:
    1. 必须有一个明确的结束条件
    
    2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
    
    3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

    四 可以修改递归最大深度

    import sys
    sys.getrecursionlimit()
    sys.setrecursionlimit(2000)
    n=1
    def test():
        global n
        print(n)
        n+=1
        test()
    
    test()
    
    虽然可以设置,但是因为不是尾递归,仍然要保存栈,内存大小一定,不可能无限递归

    五 二分法

    想从一个按照从小到大排列的数字列表中找到指定的数字,遍历的效率太低,用二分法(算法的一种,算法是解决问题的方法)可以极大低缩小问题规模

    l=[1,2,10,30,33,99,101,200,301,402] #从小到大排列的数字列表
    
    def search(num,l):
        print(l)
        if len(l) > 0:
            mid=len(l)//2
            if num > l[mid]:
                #in the right
                l=l[mid+1:]
            elif num < l[mid]:
                #in the left
                l=l[:mid]
            else:
                print('find it')
                return
            search(num,l)
        else:
            #如果值不存在,则列表切为空
            print('not exists')
            return
    search(100,l)
    
    实现类似于in的效果
    实现类似于in的效果
    l=[1,2,10,30,33,99,101,200,301,402]
    
    def search(num,l,start=0,stop=len(l)-1):
        if start <= stop:
            mid=start+(stop-start)//2
            print('start:[%s] stop:[%s] mid:[%s] mid_val:[%s]' %(start,stop,mid,l[mid]))
            if num > l[mid]:
                start=mid+1
            elif num < l[mid]:
                stop=mid-1
            else:
                print('find it',mid)
                return
            search(num,l,start,stop)
        else: #如果stop > start则意味着列表实际上已经全部切完,即切为空
            print('not exists')
            return
    
    search(301,l)
    
    实现类似于l.index(30)的效果
    实现类似于l.index(30)的效果

    六 匿名函数

    一 什么是匿名函数?

    匿名就是没有名字
    def func(x,y,z=1):
        return x+y+z
    
    匿名
    lambda x,y,z=1:x+y+z #与函数有相同的作用域,但是匿名意味着引用计数为0,使用一次就释放,除非让其有名字
    func=lambda x,y,z=1:x+y+z 
    func(1,2,3)
    #让其有名字就没有意义

    二 有名字的函数与匿名函数的对比

    #有名函数与匿名函数的对比
    有名函数:循环使用,保存了名字,通过名字就可以重复引用函数功能
    
    匿名函数:一次性使用,随时随时定义
    
    应用:max,min,sorted,map,reduce,filter
    #max
    salaries={
        "egon":3000,
        "alex":10000000,
        "wupeiqi":10000,
        "yuanhao":2000
    }
    # def func(k):
    #     return salaries[k]
    # most_salary=max(salaries,key=func )
    # # most_salary=max(salaries,key=lambda k:salaries[k] )
    # print (most_salary)
    
    
    
    #sorted
    # g=sorted(salaries,key=lambda x:salaries[x])
    # print (list(g))
    
    #map
    # names=["alex","wupeiqi","yuanhao"]
    # print (list(map(lambda name:"%s_sb"%name,names)))
    
    
    #filter
    # names=['alex_sb', 'wupeiqi_sb', 'yuanhao_sb',"egon"]
    # print (list(filter(lambda name:name.endswith("sb"),names)))
    
    
    #reduce
    
    # from functools import reduce
    # print (reduce(lambda x,y:x+y,range(101)))
    内置函数与匿名函数

    七 内置函数

    #注意:内置函数id()可以返回一个对象的身份,返回值为整数。这个整数通常对应与该对象在内存中的位置,但这与python的具体实现有关,不应该作为对身份的定义,即不够精准,最精准的还是以内存地址为准。is运算符用于比较两个对象的身份,等号比较两个对象的值,内置函数type()则返回一个对象的类型
    
    #更多内置函数:https://docs.python.org/3/library/functions.html?highlight=built#ascii 
    字典的运算:最小值,最大值,排序
    salaries={
        'egon':3000,
        'alex':100000000,
        'wupeiqi':10000,
        'yuanhao':2000
    }
    
    迭代字典,取得是key,因而比较的是key的最大和最小值
    >>> max(salaries)
    'yuanhao'
    >>> min(salaries)
    'alex'
    
    可以取values,来比较
    >>> max(salaries.values())
    >>> min(salaries.values())
    但通常我们都是想取出,工资最高的那个人名,即比较的是salaries的值,得到的是键
    >>> max(salaries,key=lambda k:salary[k])
    'alex'
    >>> min(salaries,key=lambda k:salary[k])
    'yuanhao'
    
    
    
    也可以通过zip的方式实现
    salaries_and_names=zip(salaries.values(),salaries.keys())
    
    先比较值,值相同则比较键
    >>> max(salaries_and_names)
    (100000000, 'alex')
    
    
    salaries_and_names是迭代器,因而只能访问一次
    >>> min(salaries_and_names)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: min() arg is an empty sequence
    
    
    
    sorted(iterable,key=None,reverse=False)
    
    !!!lambda与内置函数结合使用!!!
    !!!lambda与内置函数结合使用!!!
    #1、语法
    # eval(str,[,globasl[,locals]])
    # exec(str,[,globasl[,locals]])
    
    #2、区别
    #示例一:
    s='1+2+3'
    print(eval(s)) #eval用来执行表达式,并返回表达式执行的结果
    print(exec(s)) #exec用来执行语句,不会返回任何值
    '''
    None
    '''
    
    #示例二:
    print(eval('1+2+x',{'x':3},{'x':30})) #返回33
    print(exec('1+2+x',{'x':3},{'x':30})) #返回None
    
    # print(eval('for i in range(10):print(i)')) #语法错误,eval不能执行表达式
    print(exec('for i in range(10):print(i)'))
    
    eval与exec
    eval与exec

    八 阶段性练习

    1、文件内容如下,标题为:姓名,性别,年纪,薪资

    egon male 18 3000
    alex male 38 30000
    wupeiqi female 28 20000
    yuanhao female 28 10000

    要求:
    从文件中取出每一条记录放入列表中,
    列表的每个元素都是{'name':'egon','sex':'male','age':18,'salary':3000}的形式

    2 根据1得到的列表,取出薪资最高的人的信息
    3 根据1得到的列表,取出最年轻的人的信息
    4 根据1得到的列表,将每个人的信息中的名字映射成首字母大写的形式
    5 根据1得到的列表,过滤掉名字以a开头的人的信息
    6 使用递归打印斐波那契数列(前两个数的和得到第三个数,如:0 1 1 2 3 4 7...)

    7 一个嵌套很多层的列表,如l=[1,2,[3,[4,5,6,[7,8,[9,10,[11,12,13,[14,15]]]]]]],用递归取出所有的值

    #1
    with open('db.txt') as f:
        items=(line.split() for line in f)
        info=[{'name':name,'sex':sex,'age':age,'salary':salary} 
              for name,sex,age,salary in items]
    
    print(info)
    #2
    print(max(info,key=lambda dic:dic['salary']))
    
    #3
    print(min(info,key=lambda dic:dic['age']))
    
    # 4
    info_new=map(lambda item:{'name':item['name'].capitalize(),
                              'sex':item['sex'],
                              'age':item['age'],
                              'salary':item['salary']},info)
    
    print(list(info_new))
    
    #5
    g=filter(lambda item:item['name'].startswith('a'),info)
    print(list(g))
    
    #6
    #非递归
    def fib(n):
        a,b=0,1
        while a < n:
            print(a,end=' ')
            a,b=b,a+b
        print()
    
    fib(10)
    #递归
    def fib(a,b,stop):
        if  a > stop:
            return
        print(a,end=' ')
        fib(b,a+b,stop)
    
    fib(0,1,10)
    
    
    #7
    l=[1,2,[3,[4,5,6,[7,8,[9,10,[11,12,13,[14,15]]]]]]]
    
    def get(seq):
        for item in seq:
            if type(item) is list:
                get(item)
            else:
                print(item)
    get(l)
    View Code

    九 作业

    作业需求:

    模拟实现一个ATM + 购物商城程序

    1. 额度 15000或自定义
    2. 实现购物商城,买东西加入 购物车,调用信用卡接口结账
    3. 可以提现,手续费5%
    4. 每月22号出账单,每月10号为还款日,过期未还,按欠款总额 万分之5 每日计息
    5. 支持多账户登录
    6. 支持账户间转账
    7. 记录每月日常消费流水
    8. 提供还款接口
    9. ATM记录操作日志 
    10. 提供管理接口,包括添加账户、用户额度,冻结账户等。。。
    11. 用户认证用装饰器

    示例代码 https://github.com/triaquae/py3_training/tree/master/atm 

    简易流程图:https://www.processon.com/view/link/589eb841e4b0999184934329  

  • 相关阅读:
    Spark ML 文本的分类
    Linxu 安装Scala
    Nginx访问非常慢
    mysql:unknown variable 'default-character-set=utf8'
    mysql 1045
    mysql: error while loading shared libraries: libnuma.so
    elasticsearch: can not run elasticsearch as root
    Java中的Class类
    ClassLoader工作机制
    遍历机器查日志
  • 原文地址:https://www.cnblogs.com/shangdelu/p/8135394.html
Copyright © 2011-2022 走看看