命名元组、推导式、三目运算符、迭代器和生成器

命名元组、推导式、三目运算符、迭代器和生成器,第1张

命名元组、推导式、三目运算符、迭代器和生成器
# 命名元组
from collections import namedtuple

# typename: 定义这个元组的名称
# field_names: 这个元组元素的名称,可以有多种表达方式,如:‘name1 name2’ 或 ‘name1, name2’ 或 [‘name1’, ‘name2’]
tup_name = namedtuple('tup_name', ['name', 'age'])  # 创建一个命名元组的类叫 tup_name
print(type(tup_name))  #  类
a1 = tup_name('aa', age=22)  # 用类 tup_name 创建对象 a1 传参赋值
print(isinstance(a1, tuple))  # 属于元组类型,内容定义好后不可修改,命名元组比字典更省内存
print(type(a1))  #  对象
print(a1)  # tup_name(name='aa', age=22)
print(a1[0])  # 可通过索引取值
print(a1.name)  # 可通过k取值
# 列表推导式,可以用来快速生成一个有规律的列表
print([i for i in range(10)])
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 列表推导式结合if条件过滤,先运行for循环部分再运行if条件过滤最后运行for之前的部分做数据处理添加到列表
print([i + 1 for i in range(10) if i % 2 == 0])
# [1, 3, 5, 7, 9]
# 三目运算符是只要满足if条件就赋值给前面的i,否则就把else的值赋给i
number = 99
num = number if number > 5 else 0
print(num)  # 只要满足if num就是number的值,不满足就是0
# a if a>b else c if c>d else d 可以理解为 a if a>b else ( c if c>d else d )  支持嵌套
# 列表推导式结合三目运算符条件过滤,先运行for循环部分再运行三目运算符条件过滤最后运行if之前的部分做数据处理添加到列表
# 在列表推导式中三目运算符只能用在for之前
print([i if i % 2 != 0 else 0 for i in range(10)])
#  [0, 1, 0, 3, 0, 5, 0, 7, 0, 9]
# 字典推导式,可以快速生成一个有规律的字典
li = ['a', 'b', 'c', 'd']
print({k: v for k, v in enumerate(li)})
# {0: 'a', 1: 'b', 2: 'c', 3: 'd'}
name = ["张三", "李四", "王五", "李六"]  # 保存名字列表
sign = ["白羊座", "双鱼座", "狮子座", "处女座"]  # 保存星座列表
dict1 = {i: j for i, j in zip(name, sign)}  # 字典推导式
print(dict1)
# {'张三': '白羊座', '李四': '双鱼座', '王五': '狮子座', '李六': '处女座'}
ssss = 'ss=11;ss22=22;aa=11;aa22=22;cc=11;cc22=22'
print({k: v for k, v in [i.split('=') for i in ssss.split(';')]})
# {'ss': '11', 'ss22': '22', 'aa': '11', 'aa22': '22', 'cc': '11', 'cc22': '22'}
# 字典推到式同样可以在for循环后面加if条件过滤,或者在for循环之前加三目运算符
print({i for i in range(5)})  # 集合推导式

同样也有元组推导式,但是这种是错误叫法,正确叫法是生成器表达式
迭代器对象
  即实现了迭代器协议的对象
迭代器协议
  1、对象实现了__iter__方法,那么这个对象就实现了迭代协议
  2、定义了__next__方法
迭代器协议是由__iter__方法、__next__方法组成的。
Python中常见的数据类型,实现了迭代协议的有 字符串、列表、元组、集合、字典、range...
直白来说,能够使用for循环进行遍历的都叫可迭代对象,所有的迭代器都是可迭代对象
创建迭代器
  使用内置函数iter(可迭代对象)即可创建一个迭代器对象
迭代器特性
  1、可使用next()即可依次获取数据
  2、获取完毕后再next()迭代报错
迭代器的作用
  节约内存,提升程序的性能
 

li = [1, 2, 3]
itor = iter(li)
print(itor)  #  迭代器对象
print(next(itor))  # 1
print(next(itor))  # 2
print(next(itor))  # 3
print(next(itor))  # 报错 StopIteration

# 也可使用for循环去遍历迭代器,但是由于迭代器内不存放数据,存放的是数据生成规则,迭代出一条数据以后就没有这个了
# print(next(itor))  此时计算得到 1
# for i in itor:  遍历从2开始,结束即停止
#     print(i)


生成器
  是一种特殊的迭代器,具备迭代器所有的特性并有自身特有的特性,生成器内同样不存储数据,只保存生成数据的计算规则。
生成器定义方法
  1、使用生成器表达式去定义生成器 如 res = ( i for i in range(100))
  2、使用生成器函数去创建生成器
        生成器函数:只要函数中定义了yield这个关键字,那么就是一个生成器函数,生成器函数不会直接执行,会返回一个生成器

# 生成器表达式
res_g = (i for i in range(3))
print(res_g)  #  at 0x000001A404A5B200>
print(next(res_g))
print(next(res_g))


# print(next(res_g))
# print(next(res_g))  # 超出报错StopIteration
# for j in res_g:
#     print(j)

# 生成器函数
def func():
    print('111111111111111')
    yield
    print('222222222222222')
    yield 1
    print('333333333333333')


fun = func()
# 可以创建多个生成器,id不一样
print(fun)  #  at 0x000001EAE828C200> 生成器
# 当我们使用next去获取生成器中的数据(使用next对生成器进行迭代 *** 作)
print(next(fun))  # 每次执行都会到yield处并把yield后面的值返回,没有值时返回None
print(next(fun))  # 1 ,从上次执行到的位置继续执行到下一个yield并返回后面的值


# print(next(fun))  # 超出,后面没有yield时报异常StopIteration


# for i in fun:
#     print(i)  # 可以使用for循环,i值为每个yield后面返回的值

# 生成器和迭代器的区别,生成器比迭代器多的几个自身独有的特性
# 1、send()方法,类似next的进阶版,可以传参给函数内部yield之前的s,
# 使用该方法之前必须先使用最少一次next启动生成器生成过一个数据
# 否则报错TypeError: can't send non-None value to a just-started generator
# 2、close()方法,关闭该生成器,关闭后该生成器再次使用就报错StopIteration
# 生成器函数每次调用都会生成一个新的生成器,只能生成新的去调用
# 3、throw()方法,在生成器内部上一次暂停的yield处主动引发一个指定异常类型,生成器内部可以使用try
# 使用之前先使用最少一次next启动生成器生成过一个数据即可被正常捕获,否则直接抛出该异常终止运行且不能被捕获
def func1():
    for i in range(10):
        s = yield i


gen = func1()
print(next(gen))  # 0
print(gen.send(666))  # 1 ,666传给s


# print(gen.close())  # 关闭生成器
# print(next(gen))  # 关闭后再次调用报错StopIteration

def func1_Send():
    num = 1
    for i in range(10):
        s = yield i * num
        num = s or num


gen_send = func1_Send()
print(next(gen_send))  # 0
print(gen_send.send(5))  # 5 , num=5
print(next(gen_send))  # 10 , num=5
print(gen_send.send(10))  # 30 , num=10
print(next(gen_send))  # 40 , num=10


def func2():
    for i in range(10):
        try:
            s = yield i
        except TypeError:
            yield 'TypeError11'
        except ValueError:
            yield 'ValueError11'


gen2 = func2()
print(next(gen2))
print(gen2.throw(TypeError))  # TypeError11  返回值
def fun22():
    name = yield
    for i in range(5):
        if type(name) != str:
            name = '127.0.0.1'
        name = yield 'http://' + name + '/user/login'


gg = fun22()
next(gg)
res = gg.send('www.baidu.com')
print(res)  # http://www.baidu.com/user/login , www.baidu.com赋值给了第一个name,即上次暂停处
res1 = gg.send('www.sohu.com')
print(res1)  # http://www.sohu.com/user/login , www.sohu.com赋值给了第二个yield前的name,即上次暂停处
res2 = gg.send('www.sogou.com')
print(res2)  # http://www.sogou.com/user/login , www.sogou.com赋值给了第二个yield前的name,即上次暂停处

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5690084.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存