#3 slice, generator, 列表生成式,可迭代

一.切片

本质上就是js中的slice方法,只不过表达形式上有所不同,一样的是这是一个纯函数

有以下几种形式

# 使用 [:] 这种形式表示切片
[startIndex=0:endIndex=len(list)]

# 每隔几个数取一个值 [::]
[startIndex=0::numToSkip-1]
# 这种情况当为-1时,会反向元素 !!!(小技巧)

# 取区域内的元素,然后每隔几个取一个
[startIndex=0:endIndex=len(list):numToSkip-1]

具体示例

# 普通的slice
>>> L = list(range(1, 100, 2)) # 即1-100之间的奇数组成的list
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 
39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 
73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99]

# 复制整个list, 直接[:]
>>> anotherList = L[:]

# 复制部分的list
# 索引为2开始到10(不包含)
>>> partList = L[2:10]
[5, 7, 9, 11, 13, 15, 17, 19]

# 从40开始, 默认到最后
>>> partList = L[40:]
[81, 83, 85, 87, 89, 91, 93, 95, 97, 99]

# 默认从0开始
>>> partList = L[:10]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]


# 从后开始 -1为最后一个
>>> partList = L[-5:-1]
[91, 93, 95, 97]
# 后2个数
>>> partList = L[-2:]
[97, 99]

# 每隔几个数取一个
# 每隔(5 - 1) = 4个取一个
>>> L[::5]
[1, 11, 21, 31, 41, 51, 61, 71, 81, 91]

# 前10个每隔1个取一个
>>> L[:10:2]
[1, 5, 9, 13, 17]

>>> L[3:10:2]
[7, 11, 15, 19]

同样 tuple 类型 和 str 类型也可以使用切片

>>> (1, 2, 3, 4)[:3]
(1, 2, 3)

>>> s = 'ABCDEFG'
>>> s[:3]
'ABC'
>>> s[::2]
'ACEG'

# 取-1时将字符串反向
>>> s[::-1]
'GFEDCBA'

# [::-2] 则是先反向,然后每隔(2-1)个取一个值
>>> s[::-2]
'GECA'

二.迭代

python中对可迭代对象都可以使用 for...in 进行迭代操作

如何判断一个对象是否可迭代,可以使用python提供的 collections 集合中的 'isinstance' 方法,查看是否属于 Iterable 的实例

from collections import Iterable

# 对字符串str类型
>>> isinstance('abc', Iterable)
True

# 对list类型
>>> isinstance([1, 2, 3], Iterable)
True

# 对字典dict类型
>>> isinstance({'a': 1, 'b': 2}, Iterable)
True

# 对数值类型
>>> isinstance(123, Iterable)
False

字典dict 迭代

对于字典类型(dict), 可以使用 items(), values() 方法对值或实体进行迭代

>>> d = {'a': 1, 'b': 2, 'c': 3}
# 直接对键进行迭代
# 因为字典是无序的,所以输出顺序不一定
>>> for key in d:
...   print(key)     
a
c
b

# 对值进行迭代 values()
>>> for value in d.values():
...   print(value)     
3
2
1

# 对键值对进行迭代 items()
>>> for k, v in d.items():
...   print(k, '', v)     
'a' 1
'b' 2
'c' 3

list 带索引迭代

对于list要将索引也显示出来,则可以使用python内置的 enumerate() 函数将list变为 索引-值 对

>>> for i, value in enumerate(['A', 'B', 'C']):
...   print(i, value)

0 A
1 B
2 C

字符串str 迭代

>>> for ch in 'ABC':
...   print(ch)
A
B
C

for 循环同时引用2个变量

python中比较常见

>>> for x, y in [(1, 1), (2, 4), (3, 9)]:
... print(x, y)

1 1
2 4
3 9

三.列表生成式 (list comprehensions)

快速生成一个list的简写方式

比如要生成一个这样的list:

[1*1, 2*2, 3*3, 4*4, ..., 10*10]

一般写法为:

>>> L = []
>>> for x in range(1, 11):
...   L.append(x * x)

使用列表生成式,可以写为:

>>> [x * x for x in range(1, 11)]

将要生成的元素 x*x 放在前面, 后面跟着for循环即可

还可以在for后面添加条件:

# 只对偶数平方
>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]

可以添加2层循环

>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

将dict生成一个list:

>>> d = {'x': 'A', 'y': 'B', 'z': 'C'}
>>> [k + '=' + v for k, v in d.items()]
['y=B', 'x=A', 'z=C']

使用 lower() 方法将列表中的字符串都变为小写; title() 将字符串首字母大写

>>> L = ['Hello', 18, 'World']
>>> [s.lower() for s in L if isinstance(s, str)]
['hello', 'world']

另外可想而知,转换为大写的方法为 upper()

四.生成器 generator

好吧,每种语言都是相似的,python中也存在生成器,上面的列表生成式,将'[]' 改为 '()' 即可产生一个generator对象

>>> L = [x * x for x in range(10) if x % 2 == 0]
>>> L
[0, 4, 16, 36, 64]

# 生成一个generator对象
>>> g = (x * x for x in range(10) if x % 2 == 0)
>>> g
<generator object <genexpr> at 0x1022ef630>

生成器的方法 next()

>>> next(g)
0
>>> next(g)
4
>>> next(g)
16
>>> next(g)
36
>>> next(g)
64
>>> next(g)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

当然我们可以使用 for 循环来输出,不用这么麻烦

>>> for n in g:
...   print(n)
0
4
16
36
64

在函数中使用 yield 关键词,创建generator函数,比如斐波拉契数列:

def fib(max):
  n, a, b = 0, 0, 1
  while n < max:
    yield b
    a, b = b, a + b
    n += 1
  return 'done'  

值得注意的是python的这种赋值的语法,十分的简洁:

n, a, b = 0, 0, 1

# 还有
a, b = b, a + b
# 相当于
a = b
b = a + b

调用函数生成一个generator对象:

>>> g = fib(6)
>>> g
<generator object fib at 0x104feaaa0>

使用 for 循环来输出

>>> for n in g:
...   print(n)

1
1
2
3
5
8

这样一来就得不到return语句后面的值了(即'done'),如果想要拿到返回值,则必须捕获StopIteration异常,返回值包含在StopIteration的value中

>>> g = fib(6)
>>> while True:
...   try:
...     x = next(g)
...     print('g:', x)
...   except StopIteration as e:
...     print('Generator return value', e.value)
...     break

g: 1
g: 1
g: 2
g: 3
g: 5
g: 8
Generator return value: done

五.Iterable 和 Iterator

可迭代和迭代器是2个不同的概念,其中:

  • 集合类型的,如 list, dict, str, 都是Iterable的,但不是Iterator, 凡是可作用于for循环的对象都是Iterable
  • 像generator对象可使用 next() 函数的都是 Iterator的,同时也是可迭代的Iterable

比如:

from collections import Iterable

# list
>>> isinstance([], Iterable)
True

# dict
>>> isinstance({}, Iterable)
True

# str
>>> isinstance('abc', Iterable)
True

# tuple
>>> isinstance((1, 2, 3), Iterable)
True

# generator
>>> isinstance((x for x in range(10)), Iterable)
True

# 数值
>>> isinstance(100, Iterable)
False

判断一个对象是否是 Iterator

from collections import Iterator

>>> isinstance((x for x in range(10)), Iterator)
True
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance('abc', Iterator)
False

可以使用 iter() 将 list, dict, str 等Iterable变为 Iterator

>>> isinstance(iter([]), Iterator)
True

>>> isinstance(iter('abc'), Iterator)
True

python中将Iterator对象表示为一个数据流,Iterator对象可以被next()函数调用并不断的返回下一个数据,直到没有数据抛出 StopIteration 错误, Iterator的计算是 惰性的, 可以表示一个无限大的数据流

总结

本章主要将的是一些常用的数据操作:

  • 切片,和js中的slice类似,只是写法不同,还有就是可以隔几个选取1个,稍微有点差异
  • 迭代,对集合类型的数据进行for...in循环, 字典中存在 'values()', 'items()' 等方法, list如果想使用索引,可以使用内置的 enumerate() 函数
  • 列表生成式,快速生成一个list的简便写法,可以写二维或以上的for循环,还可以添加条件判断
  • 生成器,这个用来对函数进行控制,快速生成生成器对象的方式和列表生成式比较类似
  • 可迭代和迭代器的区别,以及使用 iter() 将可迭代转换为迭代器
  • 异常捕获使用 try...except ExceptType
  • 另外接触到的函数 lower(), upper(), title()

2017年3月5日 21:55:26

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容