zoukankan      html  css  js  c++  java
  • 三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数

    三元表达式

    # what:就是简写if...else...结构,且都只有一条语句
    # 语法:结果1 if 条件 else 结果2
    # 注意:结果1|2不一定要与条件有必然关系,条件只是选择结果1或结果2的判断依据
    
    # 案例:获得两个数中的大值 | 小者
    n1 = int(input('n1: '))
    n2 = int(input('n2: '))
    res = n1 if n1 > n2 else n2
    print(res)
    res = n2 if n1 > n2 else n1
    print(res)

    列表字典推导式

    # 列表推导式
    # 语法:[结果 for 结果 in 可for循环操作的对象]
    # 案例:[v for v in 'abc'] => ['a', 'b', 'c']
    
    # 产生1~10之间的偶数list => [2, 4, 6, 8, 10]
    ls = [i for i in range(2, 11, 2)]  # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    print(ls)
    
    # 1~5之间的数用奇数偶数形参list => ['奇数', '偶数', '奇数', '偶数','奇数']
    ls = ['奇数' if i % 2 != 0 else '偶数' for i in range(1, 6)]
    print(ls)
    
    ls = ('奇数' if i % 2 != 0 else '偶数' for i in range(1, 6))
    print(tuple(ls))
    
    
    #字典推导式
    # 语法:{k: v for k, v in 可for循环操作的对象(每一次循环的结果可以被解压为两个值)}
    # 案例:
    # 原数据: [('a', 1), ('b', 2)] => {'a': 1, 'b': 2}
    source = [('a', 1), ('b', 2)]
    dic = {k: v for k, v in source}
    print(dic)
    
    dic = {i: 0 for i in 'abc'}
    print(dic)
    #print({}.fromkeys('abc', 0))

    迭代器

    # 寻求一种不依赖索引,且可以循环取值的方式
    dic = {'a': 1, 'b': 2, 'c': 3}
    print(dic) # {'a': 1, 'b': 2, 'c': 3}
    
    # 通过__iter__()方法获取dic的一个不用依赖索引的取值容器
    box = dic.__iter__()
    print(box) #<dict_keyiterator object at 0x0000000001D9D4A8>
    print(box.__next__()) #a
    
    box3 = 'abc'.__iter__()
    print(box3) # <str_iterator object at 0x0000000001E7CBA8>
    print(box3.__next__()) # a
    
    box4 = {'a', 'b', 'c'}.__iter__()
    print(box4)  # <set_iterator object at 0x0000000001EBA708>
    print(box4.__next__()) # a
    print(box4.__next__()) # b
    
    '''
    1.txt内容:
    11111111
    22222222
    33333333
    44444444
    '''
    with open('1.txt', 'r', encoding='utf-8') as r:
        print(r)  # <_io.TextIOWrapper name='1.txt' mode='r' encoding='utf-8'>
        print(r.__next__())  # 11111111
        print(r.__next__())  #  22222222
    # 可迭代对象
    # 有__iter__()方法的对象都称之为 可迭代对象
    
    # 可迭代对象:可以被转化为不依赖索引取值的容器,这样的对象就叫做可迭代对象
    #       -- 对象.__iter__() 来生成不依赖索引取值的容器
    #       -- 结论:有__iter__()方法的对象都称之为 可迭代对象
    
    # 可迭代对象.__iter__() => 和该对象有关系的迭代器对象 dict_keyiterator object
    box = dic.__iter__()  
    
    # 可迭代对象有哪些:str | list | tuple | set | dict | range() | enumerate() | file | 生成器对象
    # 迭代器对象:
    # 有__next__()且可以通过__next__()进行取值的容器
    
    # 迭代器对象:可以通过__next__()的方式进行取值的容器,且取一个少一个
    #       -- 结论:有__next__()且可以通过__next__()进行取值的容器
    #       -- 注意:迭代器对象自身也拥有__iter__(), 通过该方法返回的是迭代器对象自身
    
    res = box.__next__()  # 从迭代器对象(容器)取出值,取一个少一个
    box = box.__iter__()  # 迭代器对象.__iter__()得到迭代器对象本身
    
    # 迭代器对象有哪些:enumerate() | file | 生成器对象
    # 迭代器(for循环):就是用来从可迭代对象中进行取值的循环方法 | 语法:for 变量 in 对象:
    #       -- 1.通过对象.__iter__()获取其对应的迭代器对象
    #           -- for可以操作迭代器对象及可迭代对象,统一写法,所以迭代器和可迭代对象都有__iter__()
    #       -- 2.在内部通过迭代器对象的__next__()进行取值,将值赋值给 语法中的变量,取一个少一个
    #       -- 3.当迭代器对象取完了,在内部自动捕获异常,并结束循环取值
    
    dic1 = {'a': 1, 'b': 2, 'c': 3}  # dic是可迭代对象
    dic1_box = dic1.__iter__()  # 通过__iter__()得到的是迭代器对象
    # print(len(dic1_box))  # 迭代器对象没有len()方法
    while True:
        try:
            print(dic1_box.__next__())
        except StopIteration:   #捕捉报错,并退出
            print('取完了')
            break
    
    for v in dic1:
        print(v)

    生成器

    # 生成器:自定义的迭代器对象
    def fn():
        print(1)
        yield 666
        print(2)
        yield 888
        print(3)
    
    obj = fn()  # generator object => [666, 888]
    # print(obj) # <generator object fn at 0x0000000001E24C50>
    # 去生成器中执行代码,拿到遇到的第一个yield后面的值,并停止运行
    print(obj.__next__()) # 1 666
    # 再接着上一个yield,再进行往下执行代码,再拿到下一个个yield后面的值,并停止运行
    print(obj.__next__()) # 2 888
    # 重复上面的过程,如果没有遇到yield,就报错
    print(obj.__next__()) # StopIteration
    
    # 举例
    #1、示例:生一筐鸡蛋变成给你一只老母鸡,用的时候就下蛋,这也是生成器的特性
    >>> chicken=('鸡蛋%s' %i for i in range(5))
    >>> chicken
    <generator object <genexpr> at 0x10143f200>
    >>> next(chicken)
    '鸡蛋0'
    >>> list(chicken) #因chicken可迭代,因而可以转成列表
    ['鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4',]
    
    #2、优点:省内存,一次只产生一个值在内存中
    
    # 将传入的值扩大两倍返回
    def fn1(a, b, c):
        yield a * 2
        yield b * 2
        yield c * 2
    
    # 解决方案
    def fn1(*args):
        i = 0
        while i < len(args):
            yield args[i] * 2
            i += 1
    
    for v in fn1(10, 20, 30, 40, 50):
        print(v)
    
    # 依次获取阶乘 1! 2! 3! ...
    def fn2():
        total = 1
        count = 1
        while True:
            total *= count
            yield total
            count += 1
    
    obj = fn2()
    
    print(obj.__next__())  # 1!=1
    print(obj.__next__()) # 2!=2
    print(obj.__next__()) # 3!=6
    print(obj.__next__()) # 4!=24

    了了解

    def fn3():
        msg = yield 1
        print(msg)
        yield 2
    obj3 = fn3()
    print(obj3.__next__())
    # 1.send会为当前停止的yield传入参数,内部可以通过yield来接收传入的参数
    # 2.send自身也会调用__next__()去获取下一个yield的结果
    result = obj3.send('ooo')
    print(result)
    举例:
    def fn4(peoples):
        count = 0
        print('%s在面试' % peoples[count])
        while count < len(peoples):
            name = yield peoples[count]
            count += 1
            print(name + "叫来%s来面试" % peoples[count])
    
    peoples = ['张三', '李四', '王五']
    obj4 = fn4(peoples)
    name = obj4.send(None)  # 第一次没有yield接收值,所以只能调__next__(),或是send(None)
    print(name + '面试完毕')
    while True:
        try:
            name = obj4.send(name)
            print(name + '面试完毕')
        except Exception:
            print('所有人面试完毕')
            break

    枚举对象

    # 枚举对象:为迭代器对象产生迭代索引
    
    ls = [3, 1, 2, 5, 4]
    list(enumerate(ls))  # => [(0, 3), (1, 1), (2, 2), (3, 5), (4, 4)]
    
    dic = {'a': 100, 'b': 200}
    print(list(enumerate(dic)))  # => [(0, 'a'), (1, 'b')]

    递归

    # 递归:函数直接或间接调用自己
    # 回溯:找寻答案的过程
    # 递推:通过最终的值反向一步步推出最初需要的结果
    
    # 前提:
    # 1.递归条件是有规律的
    # 2.递归必须有出口
    import sys
    print(sys.getrecursionlimit()) # 最大递归层 1000
    sys.setrecursionlimit(100) #可以修改最大递归次数
    # 举例
    # 拿递归求得年纪
    def get_age(num):
        if num == 1:
            return 58
        age = get_age(num - 1) - 2
        return age
    age = get_age(10)
    print(age)
    
    # 传入一个num,求得该num的阶乘
    # 5! = 5 * 4 * 3 * 2 * 1 = 5 * 4!
    # 4! = 4 * 3 * 2 * 1 = 4 * 3!
    # 3! = 3 * 2 * 1 = 3 * 2!
    # 2! = 2 * 1 = 2 * 1!
    # 1! = 1
    def get_total(num):
        if num == 1 or num == 0:
            return 1
        total = num * get_total(num - 1)  # 3 * 2! => 2 * 1!1 => 1 => 2 * 1
        return total
    print(get_total(3))

    匿名函数

    # 匿名函数:没有名字的函数
    # 1.用lambda声明匿名函数
    # 2.没有函数名,lambda与:之间一定是参数列表,参数列表省略(),且支持所有参数语法
    # 3.匿名函数没有函数体,只有返回值,所有省略了return,且返回值只能有一个
    #       -- (不能将多个返回值自动格式化为元组)
    # lambda 参数1, ..., 参数n: 一个返回值
    # 应用场景
    # 1.用一个变量接收,该变量就充当与函数的名字 - 不常见
    func = lambda x, y: (x + y, x - y)
    print(func(10, 20))
    
    # 2.结合内置函数来使用
    y=(max([1, 2, 6, 5, 3], key=lambda x: x))
    print(y) # 6
    dic = {
        'Bob': (1, 88888),
        'Ben': (2, 300000),
        'Tom': (3, 99999)
    }
    s = min(dic, key=lambda k: dic[k][1])  # 按薪资求最小值
    print(s) #Bob

    内置函数

    官方3.7.3列出内置函数:https://docs.python.org/zh-cn/3/library/functions.html

    # 已见过的
    # 1.类型转换:int() tuple()
    # 2.常规使用:print() input() len() next() iter() open() range() enumerate() id()
    # 3.进制转换:bin() oct() hex() 将10进制转换为2 | 8 | 16进制
    print(bin(10))  # 0b1010
    print(oct(10))  # 0o12
    print(hex(10))  # 0xa
    
    # 3.运算:abs()
    print(abs(-1))  # 绝对值
    print(chr(9326))  # 将ASCII转换为字符
    print(ord(''))  # 逆运算
    print(pow(2, 3))  # 2的3次方
    print(pow(2, 3, 3))  # 2的3次方对3求余
    print(sum([1, 2, 3]))  # 求和
    
    # 4.反射:getattr() delattr() hasattr() setattr()
    
    # 5.面向对象的相关方法:super() staticmethod() classmethod()
    def fn():pass
    print(callable(fn))  # 对象能不能被调用
    
    # 6.原义字符串
    print('a\nb')
    s = ascii('a\nb')
    print(s)
    s = repr('a\nb')
    print(s)
    print(r'a\nb')
    
    print(all([1, 0, 0]))
    print(any([0, 0, 1]))
    
    # compile() exec() eval()
    # max的工作原理
    # 1.max要去遍历所有求大值的数据,这些一一被遍历出来的数要被依次传入key=fn的fn中
    #       -- fn必须有参数,且只有一个参数,就是当前被遍历出来的被比较的数据
    # 2.max再根据fn的返回值决定比较大小的依据
    dic = {
        'owen': (1, 88888),
        'egon': (2, 300000),
        'liuXX': (3, 99999)
    }
    def fn2(k):
        # return k  # 求名字最大
        # return dic[k][0]  # 求工号最大
        return dic[k][1]  # 求薪资最大
    max_p = max(dic, key=fn2)
    print(max_p) # egon
    
    # min函数的工作原理
    # 1.min要去遍历所有求小值的数据,这些一一被遍历出来的数要被依次传入key=fn的fn中
    #       -- fn必须有参数,且只有一个参数,就是当前被遍历出来的被比较的数据
    # 2.min再根据fn的返回值决定比较大小的依据
    
    dic = {
        'owen': (1, 88888),
        'egon': (2, 300000),
        'liuXX': (3, 99999)
    }
    res = min(dic, key=lambda x: dic[x][1])
    print(res)
    
    # 排序:sorted
    dic = {
        'owen': (1, 88888),
        'egon': (2, 300000),
        'liuXX': (3, 99999)
    }
    
    # 总结:排序的可迭代对象,排序的规则,是否反转
    res = sorted(dic, key=lambda k: dic[k][1], reverse=True)  # 按薪资排序的人名list
    for k in res:
        print(k, dic[k][1])
    
    # map:映射 - 格式化每一次的遍历结果
    names = ['Owen', 'Egon', 'Liuxx']
    def fn(x):
        # print(x)
        # 将所有名字全小写
        return x.lower()
    
    res = map(fn, names)
    print(list(res))
    
    dic1 = {
        'owen': 88888,
        'egon': 300000,
        'liuXX': 99999
    }
    def fn1(x):
        dic1[x] += 1
        return 10000
    # 总结:遍历第二个参数(可迭代对象),将遍历的结果丢给第一个函数,
    # 函数有一个参数,就是一一遍历的值
    # map的作用(返回值):在当前数据基础上改变值(可以任意修改)
    res = map(fn1, dic1)
    print(list(res))
    print(dic1)
    
    # 合并:reduce
    from functools import reduce
    # 求[1, 3, 4, 2, 10]所有元素的总和
    res = reduce(lambda x, y: x + y, [1, 3, 4, 2, 10])
    print(res)
    模块举例

    练习:

    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)
    练习
  • 相关阅读:
    start tag, end tag issues in IE7, particularly in xslt transformation
    用SandCastle为注释生成chm文档
    Firebug
    架构的重点
    Linux Shell常用技巧(十) 管道组合
    Linux JDK升级
    Linux Shell常用技巧(十二) Shell编程
    Packet Tracer 5.0实验(一) 交换机的基本配置与管理
    Linux Shell常用技巧(六) sort uniq tar split
    Linux Shell常用技巧(二) grep
  • 原文地址:https://www.cnblogs.com/yangmeichong/p/10750578.html
Copyright © 2011-2022 走看看