知识点总结:
迭代器(Iterator),可迭代对象(Iterable)
- Iterable: 具有方法__iter__()的对象。该方法返回一个Iterator
- Iterator: 具有方法__next__()的对象__next__()可以被直接调用,迭代到超过末尾会抛出异常。同时具有__iter__()返回自身即可。
所以迭代器一定是可迭代对象!!!
通过for迭代Iterable
# 通过for迭代tuple
for i in (1, 2, 3):
print(i)
# 通过for迭代dict
for k, v in {'k1': 'key', 'k2': 'value2'}.items():
print(k, v)
# 通过for迭代一个file,按行迭代
# 实际open()返回的是一个stream, Iterator类型
f = open('data.txt', 'r', encoding='utf8')
for line in f:
print(line)
- 注意: list/dict/tuple等为可迭代对象。实际for的底层会调用其__iter__()得到Iterator进而调用__next__(), 下面介绍
- print(isinstance(i, Iterable)) 判断是否为Iterable
- print(isinstance(i, Iterator)) 判断是否为Iterator
from collections import Iterable, Iterator
>>> i = []
>>> isinstance(i, Iterable)
True
>>> isinstance(i, Iterator)
False
# i 具有__iter__()方法,其为Iterable可迭代对象
>>> i.__iter__()
<list_iterator object at 0x00000280FD9490B8>
iter() 说明
'''
iter(iterable) -> iterator
iter(callable, sentinel) -> iterator
Get an iterator from an object. In the first form, the argument must
supply its own iterator, or be a sequence.
In the second form, the callable is called until it returns the sentinel.
'''
- 可用iter()封装list,将list(可迭代对象)转为Iterator迭代器
- 调用iter()获得迭代器的两种方式
l = [1, 2, 3]
# 1. 之际调用Iterable的__iter__()方法
l.__iter__()
# 2. 通过函数iter()获取迭代器
iter(l)
# 得到Iterator后可进而调用next()获得值
print(l.__iter__().__next__())
- 调用next()迭代方法的两种方式
# 1. 直接调用对象__next__()方法
print(f.__next__())
# 2. 通过函数next()调用
print(next(f))
urls = ['www.baidu.com', 'mp.csdn.net']
i = iter(urls)
- 多种方式实现迭代list
l = [1,2,3]
res = []
# 用for实现
for x in l:
res.append(x**2)
# 用iter()实现相同功能
i = iter(l)
while True:
try:
res.append(next(i)**2)
except StopIteration:
break
res = [x**2 for x in l]
print(res)
# 用推导实现相同功能
l = [1, 2, 3, 4]
res = [x for x in l if x % 2 == 0]
print(res)
生成内置可迭代对象的函数介绍(Iterable 具有__iter__())
# 1. range()
r = range(0, 5)
for i in r:
print(i)
# 输出
0
1
2
3
4
# 2. zip() 合并集合
result = zip(['x', 'y', 'z'], [1, 2, 3])
for i in result:
print(i)
# 输出
('x', 1)
('y', 2)
('z', 3)
# 3. map()
def times_two(x):
x *= 2
return x
l = list(map(times_two, [1, 2, 3]))
print(l)
# 输出
[2, 4, 6]
# 4. filter()
函数
- 最大化代码重用
- 最小代码冗余
- 过程分解,降低代码逻辑复杂度
函数的定义
# def 函数名(参数) return 返回值
def function(args):
print(args)
return 'return'
# 函数实现找到两个string共同部分
def intersect(seq1, seq2):
res = []
for x in seq1:
if x in seq2:
res.append(x)
return res
s1 = 'abcdfe'
s2 = 'bcd'
print(intersect(s1, s2))
# 使用推导实现
res = [x for x in s1 if x in s2]
print(res)
变量作用域
x = 55
def func():
x = 99
print(x)
print('Global x:', x)
print('Local x: ', end='')
func()
#输出 函数内逻辑没有改变外部变量(全局变量)
Global x: 55
Local x: 99
- 使用全局变量用global标记
x2 = 55
def func2():
global x2
x2 = 99
print(x2)
print('Global x2:', x2)
print('Local x2: ', end='')
func2()
print('Global x2:', x2)
#输出 函数逻辑改变了全局变量
Global x2: 55
Local x2: 99
Global x2: 99
# 其它作用范围
# Built-in : 作用域高于 global
# Enclousure : 封装域 nonlocal
# 内层函数不会修改外层 x
def func():
x = 100
def nested():
# 如果使用nonlocal标记,则使用外层函数的x
# nonlocal x
x = 99
print(x)
nested()
print(x)
参数传递方式
当参数向函数传递
- 不可变类型先做副本再传入,函数内不会影响原变量
- 可变类型传入地址引用,函数内的操作影响变量值
# 传入不可变类型,不改变原变量值
def change_num(x):
x += 5
x = 5
print('x = {}'.format(x))
change_num(x)
print('x = {}'.format(x))
# 输出
x = 5
x = 5
# 传入可变类型,改变变量值
def change_list(l):
l[0] = 'change'
l = [1, 2, 3]
print(l)
# 函数操作将改变l内的值,如不希望改变则传入l.copy() 或 l[:] 即可
change_list(l)
print(l)
# 输出
[1, 2, 3]
['change', 2, 3]