# 02,迭代器
# 可迭代对象:内部含有__iter__
# 迭代器:可迭代对象.__iter__()
# 迭代器:内部含有__iter__且__next__
# 判断 __iter__ 在不在dir(对象中)
# isinstance()
# 节省内存。
# 惰性机制。
# 单向不可逆。
# for循环的机制:
# while
# pass
# 可迭代对象
# 迭代器
# 两者区别
# 模拟for循环机制
#
# 03,生成器
# 本质上是迭代器,用python代码构建的。
# 生成器定义
# 生成器的写法
# yield
# send
#迭代器
#可迭代对象
# s1 = '123'
# for i in s1:
# print(i)
#错误例子:
# int object is not iterable
# for i in 123:
# print(i)
#内部含有__iter__方法的就是可迭代对象,遵循可迭代协议。
#dir
# print(dir('123')) # '__iter__'
# print('__iter__' in dir([1, 2, 3]))
# print('__iter__' in dir({'name':'alex'}))
# print('__iter__' in dir({'name'}))
# print('__iter__' in dir((1, 2, 3)))
# print('__iter__' in dir(1)) # False
# print('__iter__' in dir(True)) # False
# 可迭代对象通过.__iter__()可以转换成迭代器,满足迭代器协议。
# # 内部含有__iter__ 且 __next__方法的就是迭代器。
# l = [1, 2, 3,5]
# l_obj = l.__iter__()
# print(l_obj)
# 迭代器的取值两种方法:
# 方法一:__next__()
# print(l_obj.__next__())
# print(l_obj.__next__())
# print(l_obj.__next__())
# print(l_obj.__next__())
# 方法二 for循环
# for i in l_obj:
# print(i)
# print('__next__' in dir(l_obj))
# 第二种判断方式:
# from collections import Iterable #迭代对象
# from collections import Iterator #迭代器
# print(isinstance('123', Iterable))
# print(isinstance('123', Iterator))
# 实际上可迭代对象是不可以一个一个的一次取值的,因为他没有__next__方法。
# for循环提供一个机制:
# 1,将可迭代对象转化成迭代器。
# 2,利用__next__进行取值。
# 3,用try异常处理方法防止报错。
# l = [1, 2, 3, 4, 5]
# l_obj = l.__iter__()
# while True:
# try:
# print(l_obj.__next__())
# except Exception:
# break
#迭代器:
# 1,节省内存。
# 2,满足惰性机制。
# 3,取值过程不可逆(一条路走到黑)。
#生成器
# 生成器本质也是迭代器,生成器是自己用Python写的迭代器。
# 1,通过生成器函数构建。
# 2,通过生成器推导式构建。
# def func1():
# print(666)
# return 222
# ret=func1()
# print(ret)
def func1():
print(11)
print(333)
yield 222
print(666)
yield 777
g_obj=func1() #生成器对象 generator object
print(g_obj.__next__())
print(g_obj.__next__())
# def cloth1():
# for i in range(1,10001):
# print('衣服%s' % i)
# cloth1()
def cloth2():
for i in range(1,10001):
yield '衣服%s'%i
g=cloth2()
for i in range(1,51):
print(g.__next__())
for s in range(51,201):
print(g.__next__())
# send :
# 1,给上一个yiled整体发送一个值
# 2, send不能给最后一个yiled发送值
# 3, 获取第一个值的时候,不能用send只能用next
def func1():
count=yield 222
print(count)
yield 777
yield 888
g_obj=func1()
# print(g_obj.__next__())
print(g_obj.send('wusir'))
#知识点补充
#1,装饰器:
#装饰器的本质是闭包。
# 开放封闭原则。
#
'''
1.对扩展是开放的
为什么要对扩展开放呢?
我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。
2.对修改是封闭的
为什么要对修改封闭呢?
就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,
很有可能影响其他已经在使用该函数的用户。
装饰器完美的遵循了这个开放封闭原则。
'''
# count = 1
#
# def func1():
# print(count)
# func1()
#局部作用域可以对全局作用域的变量进行引用。
# count = 1
# 函数内部如果有变量名与全局变量名相同且对此变量进行改变,
# Python 就会将你引用的那个变量视为局部定义的变量,但是局部没定义,
# 则他会报错。
# def func1():
# count1 = count + 1
# print(count)
# func1()
#
# def func1():
# count = 3
# def inner():
# count = count + 1
# inner()
# print(count)
# func1()
#函数中如果使用global + 变量 必须是第一次使用这个变量。
# flag = True
# def func1():
#
# if flag:
# print(333)
# global flag
# flag = False
# func1()
# flag = True
# while flag:
# print(333)
# flag = False
# print(222)
#for if while 没有开辟临时空间。
#globals() locals()
# locals :函数会以字典的类型返回 当前位置 的全部 局部变量。
#
# globals:函数以字典的类型返回全部全局变量。
#
# def extendList(val,list=[]):
# list.append(val)
# # print(globals())
# print(locals()) # {'list': [1], 'val': 1}
# def inner():
# a = 3
# b = 4
# print(locals())
# inner()
# return list
# ret = extendList(1)
# print(globals()) # 'ret': [1]
# print(locals())
# 列表推导式:能用列表推导式完成的,用python代码都可以完成。
# 用一句话构建一个你想要的列表。
# 优点:简单,稍微难理解。
# 缺点: 不能用debug。
# li = []
# for i in range(1, 12):
# li.append(i)
# print(li)
# li = [i for i in range(1, 12)]
# [ 变量(加工后的变量) for 变量 in 可迭代对象 ] 遍历模式
# print(li)
# [ 变量(加工后的变量) for 变量 in 可迭代对象 ] 遍历模式
# [ 变量(加工后的变量) for 变量 in 可迭代对象 if 判断] 筛选模式
# l1 = [i for i in range(1, 101) if i % 2 == 0]
# print(l1)
#1,筛选,100以内所有的奇数。
# l2 = [i for i in range(1, 101) if i % 2 == 1]
# l2 = [i for i in range(1, 101, 2)]
# print(l2)
#2,10以内所有数的平方。 [1,4,9,16.。。100]
# print([i*i for i in range(1, 11)])
#3,将100以内所有内被三整除的数留到列表中。
# print([i for i in range(1,101) if i % 3 == 0])
# 列表推导式 简单明了,但是占内存
# 生成器表达式 节省内存,不易看出。
# names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
# ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
# l3 = [ name for i in names for name in i if name.count('e') == 2]
# print(l3)
# mcase = {'a': 10, 'b': 34}
# mcase_frequency = {mcase[k]: k for k in mcase}
# print(mcase_frequency)