Fork me on GitHub

day-13

1. 迭代器

python中一切皆对象

迭代器和装饰器不同,迭代器只是一个称呼而已。

1.1 可迭代对象

含有 .__iter__ 方法的数据类型叫做可迭代对象,除了数字类型,所有数据类型都是可迭代对象。

x = 10  # 不是可迭代对象

s = 'abc'
s.__iter__()

lt = [1, 2, 3]
lt.__iter__()

tup = (1,)
tup.__iter__()

dic = {'a': 1}
dic.__iter__()

se = {1}
se.__iter__()

fw = open('test.txt', 'a+', encoding='utf8')
fw.seek(0, 0)
fw.__iter__()

1.2 迭代器对象

含有 .__iter__.__next__ 方法的对象就是迭代器对象,只有文件是迭代器对象

dic = {'a': 1, 'b': 2, 'c': 3}
dic_iter = dic.__iter__()	# 2.其他类型都需要这样间接使用
print(dic_iter.__next__())
print(dic_iter.__next__())
print(dic_iter.__next__())

fw = open('test.txt', 'a+', encoding='utf8')
fw.seek(0, 0)
fw.__iter__()
fw.__next__()	# 1.文件类型可以直接使用 .__next__() 方法
print(fw.__next__())
print(fw.__next__())
print(fw.__next__())

运行结果:

a
b
c
------------------------------
1

2

3


Process finished with exit code 0

1.2.1 迭代器对象的作用

提供了一种不依赖索引取值的手段。

1.2.2 for 循环的原理

# for循环原理(for循环本质就是一个while循环,只不过是一个一定可控的while循环)
dic = {'a': 1, 'b': 2, 'c': 3}	# 要求逐个取出字典的 key

dic_iter = dic.__iter__()
while True:
    try:
        print(dic_iter.__next__())
    except StopIteration:
        break
        
# print('-'*30)

for i in dic:  # for循环 --> 迭代循环
    print(i)
    
# 标准版
# def for(iterable):
#     iterator = iterable.__iter__()
#     while True:
#         try:
#             print(iterator.__next__())
#         except StopIteration:
#             break
a
b
c
------------------------------
a
b
c

Process finished with exit code 0

1.3 总结

  • 可迭代对象:
    • 含有 .__iter__ 方法叫做可迭代对象
    • 除了数字类型都是可迭代对象
    • 可迭代对象使用 .__iter__ 变成迭代器
    • 可迭代对象不一定是迭代器对象
  • 迭代器对象:
    • 含有 .__iter__.__next__ 方法叫做迭代器对象
    • 只有文件是迭代器对象
    • 迭代器使用 .__iter__ 依然是迭代器
    • 迭代器对象一定是可迭代对象

2. 三元表达式

格式:条件成立时的返回值 if 条件 else 条件不成立时的返回值

x = 10
y = 20
if x > y:
    print(x)
else:
    print(y)

使用三元表达式:

print(x) if x > y else print(y)

3. 列表推导式

创建一个列表

lt = []

for i in range(10):
    lt.append(i)

使用列表推导式:

lt = [i for i in range(10)]	
lt = [i ** 2 for i in range(10)]	# in 后面加可迭代类型

4. 字典生成式

4.1 字典生成式

生成一个列表:

dic = {}

for i in range(10):
    dic[i] = i ** 2

使用字典生成式:

dic = {i:i**2 for i in range(10)}

4.2 zip()方法

lt1 = ['a', 'b', 'c']
lt2 = [1, 2, 3]

dic = {k: v for k, v in zip(lt1, lt2)}
print(dic)

zip() 方法的说明:

res = zip([1, 2, 3], [4, 2, 3, 4, 2, 3, 4, 2, 3],
          'abcadsfasdfasdf')  # res是一个迭代器,__next__返回元组
print(res.__next__())  # type:tuple
print(res.__next__())  # type:tuple
print(res.__next__())  # type:tuple

打印结果:

(1, 4, 'a')
(2, 2, 'b')
(3, 3, 'c')

Process finished with exit code 0

5. 生成器

生成器:本质上是迭代器,它提供了一种方便的自定义迭代器的途径。

含有 yield 关键字的函数叫做生成器

5.1 生成器和函数的区别

def func():
    print(1)


def ge():
    yield 1


print(func)
print(ge)	
print('-' * 30)
print(func())
print(ge())

运行结果:

<function func at 0x00000221B4673798>	# 打印出了函数 func 的内存地址
<function ge at 0x00000221B4673828>	# 打印出了函数 ge 的内存地址
------------------------------
1
None	# func() 调用了函数,并得到了默认的返回值 None
<generator object ge at 0x00000221B4674048>	# ge() 返回了生成器对象的地址,并没有执行里面的代码

Process finished with exit code 0

5.2 生成器的特性

  • 生成器的本质是迭代器
def ge():
    yield 1	# 一个yield相当于一个next; 暂停函数
    yield 2
    yield 3

    
g = ge()	# 得到一个生成器
print(g.__next__())
print(g.__next__())
print(g.__next__())

运行结果:

1
2
3

Process finished with exit code 0
  • yield 的特性
    • 暂停函数
    • 通过 .__next__() 取值

5.3 练习-简单的 range 方法

def range(start):
    count = 0
    while count < start:
        yield (count)
        count += 1


g = range(3)
print(g.__next__())
print(g.__next__())
print(g.__next__())

6. 生成器表达式

生成一个生成器:

# 生成器表达式
g = (i for i in range(5))

生成器表达式和列表推导式

# 生成器表达式
g = (i for i in range(5))	# 节省内存空间,需要用的时候取出来
# 列表推导式
lt = [i for i in range(5)]	# 一次性生成数据,占用内存空间

7. 递归

  • 递归:函数内部直接或间接的又调用了函数本身

    # 这种形式叫做递归
    def a():
        x = 1
        print(x)
        a()
    a()
    

    由于每一次的递归,都没有结束函数的条件,并且每一次递归,都会开辟新的内存空间存放变量值,一直这样的话内存会爆掉,所以 python 给了限制最多递归1000次。

  • 真正的递归必须有退出的条件

    count = 0
    
    
    def a():
        global count
        count += 1
        print(count)
        if count == 5:
            return
        a()
    
    
    a()
    

    运行结果:

    1
    2
    3
    4
    5
    
    Process finished with exit code 0
    

    7.1 总结

    递归:

    • 函数内部调用函数自己
    • 必须要有退出条件
    • 递归必须要有规律
posted @ 2019-09-24 17:15  Yugaliii  阅读(84)  评论(0编辑  收藏  举报