Python学习(三)

切片

我们要获取一个list或者tuple里面的元素,我们一般是通过for循环来获取的,但是要获取指定索引范围内的元素,用for循环的话略显繁琐,不过,Python给我们提供了切片(Slice)操作符

l = [1, 2, 3, 4, 5]
print(l[1:4])           # [2, 3, 4]
print(l[-4:-1])         # [2, 3, 4] 
print(l[2:])            # [3, 4, 5]

通过切片的方式获取的元素一般是包含头不包含尾

在Python中并没有提供像Java中对字符串进行截取的函数,不过,字符串可以通过切片来实现截取的功能

print("ABCDEFG"[2:5])       # CDE

迭代

我们之前通过for...in ..有对list和tuple进行循环,这种循环叫迭代(Iteration)。能够被迭代的对象,我们称之为迭代对象(Iterable),那么如何判断一个对象是否为Iterable了?还记得上篇文章有一个函数参数类型检查的吗?是的,就是通过isinstance函数来判断。

from collections import Iterable

print(isinstance("abc", Iterable))      # True
print(isinstance([], Iterable))         # True
print(isinstance((), Iterable))         # True
print(isinstance({}, Iterable))         # True
print(isinstance(123, Iterable))        # False

list的迭代比较简单,不过我们只能够获取元素,如果要获取list中元素的索引的话,需要借助enumerate函数;默认是从0开始的,当然也可以从自己指定数开始

l = ["手机", "电脑", "飞机", "火车"]
for index, value in enumerate(l):
    print(index, value)
print("-----------------")
for index, value in enumerate(l, 1):
    print(index, value)

打印结果:

0 手机
1 电脑
2 飞机
3 火车
-----------------
1 手机
2 电脑
3 飞机
4 火车

默认情况下,dict的迭代是key,我们也可以只迭代value,或者都迭代

d = {"1": "手机", "2": "电脑", "3": "飞机", "4": "火车"}
for key in d:
    print(key)
print("-----------------")
for value in d.values():
    print(value)
print("-----------------")
for key, value in d.items():
    print(key, value)

打印结果如下:

3
4
2
1
-----------------
飞机
火车
电脑
手机
-----------------
3 飞机
4 火车
2 电脑
1 手机

列表生成式

通过list函数可以生成一个list列表,如:

# range(start,stop,间隔数),根据间隔数获取指定范围内的数,默认为0
print(list(range(1, 11)))       # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

若要生成[1x1, 2x2, 3x3, ..., 10x10],可以这样写:

print(list(x * x for x in range(1, 11)))    # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

若只需要生成偶数的平方,可以这样写:

print(list(x * x for x in range(1, 11) if x % 2 == 0))      # [4, 16, 36, 64, 100]

for循环嵌套

print(list(m + n for m in "AB" for n in "CD"))      # ['AC', 'AD', 'BC', 'BD']

生成器(generator)

  • 作用
生成器是用来在循环的过程中不断推算出后续的元素,这样就不必创建完整的list,从而节省大量的空间。
  • 创建方式

    • 把一个列表生成式的[]改成()

        g = (x * x for x in range(1, 11, 2))
        print(g)            # <generator object <genexpr> at 0x102184990>
        # 通过next函数来获取元素
        print(next(g))  # 1
        print(next(g))  # 9
        print(next(g))  # 25
        print(next(g))  # 49
        print(next(g))  # 81
        print(next(g))  # StopIteration
      

      当最后一个元素被计算出来后,再去计算下一个元素的话,会报一个StopIteration错误

    • 在函数定义中包含yield关键字

        def odd():
        print("step 1")
        yield 1
        print("step 2")
        yield 2
        print("step 3")
        yield 3
      

      获取元素:

        g = odd()
        print(g)
        print(next(g))
        print(next(g))
        print(next(g))
      

      打印结果如下:

        <generator object odd at 0x100784990>
        step 1
        1
        step 2
        2
        step 3
        3
      

      从打印结果可以看出,当第一次通过next函数获取元素时,由于遇到了yield,所以此时函数的执行就会被中断,将yield设定的值返回给调用者;然后第二次调用开始,此时程序会从上次中断的位置重新开始,继续执行代码,若又遇到yield,又会被中断,后面的就依此类推

  • 迭代生成器

    上面从生成器中去获取元素都是通过一个一个去调用next函数,很显然,这种变态的做法,我们程序员是不可能去做的。我们一般是通过for、while循环来获取的。还是以上面的odd函数为例。

      while True:
      try:
          r = next(g)
          print("g:", r)
      except StopIteration as e:
          print("Generator return value:", e.value)
          # 遇到StopIteration就退出循环
          break   
      
      # 打印结果如下:    
      g: 1
      g: 2
      g: 3
      Generator return value: None
          
      # 这里的try... except...类似于Java中的try...catch语句
    

迭代器(Iterator)

之前我们有学习到迭代对象,凡是可以被for循环的对象统称为可迭代对象(Iterable),当时是用isinstance函数来判断一个对象是否是可迭代对象。

可以被next函数调用并不断返回下一个值的对象称为迭代器(Iterator)。也可以用isinstance函数来判断哪些数据类型属于Iterator

from collections import Iterator

print(isinstance((x for x in range(1, 10)), Iterator))  # True
print(isinstance([], Iterator))                         # False
print(isinstance({}, Iterator))                         # False
print(isinstance("abc", Iterator))                      # False

虽然list,dict,str不是Iterator,但可以通过iter函数来进行转换

print(isinstance(iter(()), Iterator))                   # True

为什么list、dict、str等数据类型不是Iterator?

这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算

Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

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

推荐阅读更多精彩内容