• 三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数


    三元表达式

    # 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)
    练习
  • 相关阅读:
    JavaEE XML XSL转换(XSLT)
    Java 并发 中断线程
    Java 并发 线程同步
    Java 并发 关键字volatile
    Java 并发 线程的优先级
    Java 并发 线程属性
    Java 并发 线程的生命周期
    Java NIO Channel和Buffer
    Java NIO Channel之FileChannel [ 转载 ]
    VUE CLI3 less 全局变量引用
  • 原文地址:https://www.cnblogs.com/yangmeichong/p/10750578.html
Copyright © 2020-2023  润新知