一、切片
L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']
# 取前三个元素
# 如果第一个索引是0,还可以省略:
L[0:3]
L[:3]
['Michael', 'Sarah', 'Tracy']
# 从索引1开始,取出2个元素出来
L[1:3]
['Sarah', 'Tracy']
# Python支持倒数切片
L[-2:]
['Bob', 'Jack']
L[-2:-1]
['Bob']
S = list(range(100))
print(S)
# 取前10个数
print(S[0:10])
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 取后10个数
print(S[-10:])
# [90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
# 前11-12个数
print(S[11:22])
# [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
# 前10个,每两个取一个
print(S[0:10:2])
print(S[:10:2])
# [0, 2, 4, 6, 8]
# 所有数,每5个取一个
print(S[:100:5])
# [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]
# 复制一个list
print(S[:])
T = (1,2,3,4,5,6,7,8,9,10)
print(T[:3])
# (1, 2, 3)
# 字符串也可以看做成一个list
Str = 'ABCDEFG'
print(Str[0:3])
# ABC
# 利用切片操作,实现一个trim()函数,去除字符串首尾的空格
def trim(s):
start = 0
end = len(s)
# 找到字符串首部的空格
while start < end and s[start] == ' ':
start += 1
# 找到字符串尾部的空格
while end > start and s[end-1] == ' ':
end -= 1
return s[start:end]
二、迭代
如果给定一个list
或tuple
,我们可以通过for
循环来遍历这个list
或tuple
,这种遍历我们称为迭代(Iteration)。
字典可以迭代:
d = {'a':1, 'b':2,'c':3}
for key in d:
print(key)
for value in d.values():
print(value)
字符串可以迭代
d = {'a':1,'b':2,'c':3}
for key in d:
print(key)
for value in d.values():
print(value)
# 同时迭代key和value
for key, value in d.items()
print(key,value)
# 输出结果
a
c
b
1
2
3
a 1
b 2
c 3
'''
items()是一个字典(dict)的方法,用于返回字典中所有键值对的元组。每个元组包含两个元素,第一个元素是键(key),第二个元素是对应的值(value)。
在for key, value in d.items()这个语句中,d是一个字典对象,items()方法会返回一个包含所有键值对的可迭代对象。通过for循环遍历这个可迭代对象,每次迭代时,将键值对解包为key和value两个变量,可以对每个键值对进行操作。
'''
使用迭代查找一个list中最小和最大值,并返回一个tuple:
def findMinAndMax(L):
#没有初始化max_value
for i in L:
if i > L[0]:
max_value = i
if i < L[0]:
min_value = i
print(max_value,min_value)
findMinAndMax([1,2,3,1])
# 报错
'''
Traceback (most recent call last):
File "D:\pythonProject\高级特性\迭代.py", line 44, in <module>
findMinAndMax([1,2,3,1])
File "D:\pythonProject\高级特性\迭代.py", line 43, in findMinAndMax
print(max_value,min_value)
UnboundLocalError: local variable 'min_value' referenced before assignment
'''
# 解释报错原因
'''
在您提供的代码中,max_value和min_value在某些条件下才会被赋值。如果这些条件从未满足,这些变量将不会被初始化,导致UnboundLocalError。
在您的代码中,由于列表[1,2,3]中的所有元素都不会小于第一个元素(L[0]),min_value从未被赋值。
此外,即使这些条件满足,这些变量也只在if语句的作用域内部有效,而不是整个函数的作用域。
为了确保这些变量在整个函数中都是可用的,您需要在循环之前初始化它们。
此外,您的比较逻辑不应该只与列表的第一个元素比较,而应该与当前已知的最大值或最小值比较。
'''
# 修复代码
def findMinAndMax(L):
if not L: # 如果列表为空,返回None
return (None, None)
max_value = L[0] # 初始化为列表的第一个元素
min_value = L[0] # 初始化为列表的第一个元素
for i in L:
if i > max_value: # 如果当前元素大于已知最大值
max_value = i
if i < min_value: # 如果当前元素小于已知最小值
min_value = i
print(max_value, min_value) # 在这里打印最大值和最小值
findMinAndMax([1, 2, 3])
三、列表生成式
# 生成[1*1,2*2,3*3,4*4,...,10*10]
L =[]
for i in range(1,11):
L.append(i * i)
print(L)
# 使用列表生成器
A = [x*x for x in range(1,11)]
print(A)
# 使用if判断
B = [x*x for x in range(1,11) if x%2 ==0]
print(B)
# 使用两层循环生成全排列
C = [m+n for m in 'ABC' for n in 'XYZ']
print(C)
# 使用运用列表生成式列出当前文件夹下的所有文件名称
import os
D= [d for d in os.listdir('.')] # os.listdir可以列出文件和目录
print(D)
# for循环可以同时使用多个变量,如dict的items(),可以同时迭代key和value
dict = {'A':'X','B':'Y','C':'Z'}
for key,value in dict.items():
print(key, '=', value)
# 使用两个变量来生成list
dict = {'A':'X','B':'Y','C':'Z'}
F = [k+'='+v for k,v in dict.items()]
print(F)
# 将大写变成小写
L = ['Hello', 'World', 'IBM', 'Apple']
G = [l.lower() for l in L]
print(G)
# if...else..用法
# 示例
'''
H = [x for x in range(1,11) if x%2 == 0]
print(H)
'''
# 输出结果
'''
File "D:\pythonProject\高级特性\列表生成式.py", line 45
I = [x if x%2 == 0 for x in range(1,11)]
^^^^^^^^^^^^^
SyntaxError: expected 'else' after 'if' expression
'''
# if写在for前面的时候,前面必须加else,否则报错
# 这是因为,for前面是一个表达式,它必须根据x计算出一个结果。表达式if x%2 == 0无法根据x计算出结果,因为缺少else
J = [x if x%2 == 0 else -x for x in range(1,11)]
print(J)
# 在一个列表生成式中,for前面的if ... else是表达式,而for后面的if是过滤条件,不能带else
四、生成器
通过列表生成式,可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。如果列表元素可以按照某种算法推算出来,那么就可以在循环的过程中不断推算出后续的元素。
在Python中,这种一边循环一边计算的机制,称为生成器:generator。
生成generator有多种方法:
方法一、将列表生成式的[]改为()
>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630>
创建L
和g
的区别仅在于最外层的[]
和()
,L
是一个list,而g
是一个generator。
通过next()
函数获得generator的下一个返回值:
>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
25
>>> next(g)
36
>>> next(g)
49
>>> next(g)
64
>>> next(g)
81
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
generator保存的是算法,每次调用next(g)
,就计算出g
的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration
的错误。
通过for
循环来迭代generator,可以不需要关心StopIteration
的错误。
>>> g = (x * x for x in range(10))
>>> for n in g:
... print(n)
...
0
1
4
9
16
25
36
49
64
81
方法二、通过函数实现
如果推算的算法比较复杂,用类似列表生成式的for
循环无法实现的时候,可以用函数来实现。
比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:
1, 1, 2, 3, 5, 8, 13, 21, 34, ...
可以用函数表示为:
def fib(max):
n, a, b = 0, 0, 1
while n < max:
print(b)
a, b = b, a + b
n = n + 1
return 'done'
要把fib
函数变成generator函数,只需要把print(b)
改为yield b
即可:
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
调用函数:
>>> f = fib(6)
>>> f
<generator object fib at 0x104feaaa0>
相较于普通函数,generator的函数在每次调用next()
的时候执行,遇到yield
语句返回,再次执行时从上次返回的yield
语句处继续执行。
举个简单的例子,定义一个generator函数,依次返回数字1,3,5:
def odd():
print('step 1')
yield 1
print('step 2')
yield(3)
print('step 3')
yield(5)
调用该generator函数时,首先要生成一个generator对象,然后用next()
函数不断获得下一个返回值:
>>> o = odd()
>>> next(o)
step 1
1
>>> next(o)
step 2
3
>>> next(o)
step 3
5
>>> next(o)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
next()函数的一种错误用法:
>>> next(odd())
step 1
1
>>> next(odd())
step 1
1
>>> next(odd())
step 1
1
原因在于odd()
会创建一个新的generator对象,上述代码实际上创建了3个完全独立的generator,对3个generator分别调用next()
当然每个都会返回第一个值。
正确的写法是创建一个generator对象,然后不断对这一个generator对象调用next()
:
>>> g = odd()
>>> next(g)
step 1
1
>>> next(g)
step 2
3
>>> next(g)
step 3
5
五、迭代器
可以使用for
循环的数据类型有以下几种:
一类是集合数据类型,如list
、tuple
、dict
、set
、str
等;
一类是generator
,包括生成器和带yield
的generator function。
(一)使用isinstance()
判断一个对象是否是Iterable
对象
>>> from collections.abc import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance('abc', Iterable)
True
>>> isinstance((x for x in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False
可以被next()
函数调用并不断返回下一个值的对象称为迭代器:Iterator
。
(二)使用isinstance()
判断一个对象是否是Iterator
对象:
>>> from collections.abc import Iterator
>>> isinstance((x for x in range(10)), Iterator)
True
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance('abc', Iterator)
False
生成器都是Iterator
对象,但list
、dict
、str
虽然是Iterable
,却不是Iterator
。
把list
、dict
、str
等Iterable
变成Iterator
可以使用iter()
函数:
>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True
(三)总结
- 凡是可作用于
for
循环的对象都是Iterable
类型; - 凡是可作用于
next()
函数的对象都是Iterator
类型,它们表示一个惰性计算的序列; - 集合数据类型如
list
、dict
、str
等是Iterable
但不是Iterator
,不过可以通过iter()
函数获得一个Iterator
对象。
评论 (0)