1. 程式人生 > >python學習(8)——高階特性

python學習(8)——高階特性

高階特性

切片(關於list和tuple的操作)

可以將list和tuple甚至於字串的選擇性輸出
標準格式
L[(這裡填入選數的開始序號):(這裡填入選數的結束序號): (這裡填入每幾個數選取一個數) ]
結束序號所在的資料不會被輸出

注意

1.開始和介紹都是填的序號,而不是第幾個
2.開始序號如果從0 開始可以省略,比如 L[:3]
3.支援倒數切片L[-2:] (可省略結尾,但結尾不是-1!)
這裡寫圖片描述
4.切片輸出的資料是不包括結束序號所在的資料的,所以L[-2:-1]只有一個數輸出!!!
5.每幾個數輸出一個數可以連帶前面的冒號省略,預設每個都取,注意是每幾而不是每隔

例一

>>> L[0:3]   
['Michael', 'Sarah', 'Tracy']
>>> L[:3]   
['Michael', 'Sarah', 'Tracy']
>>> L[1:3]   
['Sarah', 'Tracy']
>>> L[-2:]
['Bob', 'Jack']
>>> L[-2:-1]
['Bob']

例二

切片操作十分有用。我們先建立一個0-99的數列:

>>> L = list(range(100))
>>> L
[0
, 1, 2, 3, ..., 99]

可以通過切片輕鬆取出某一段數列。比如前10個數:

>>> L[:10]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
後10個數:

>>> L[-10:]
[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]

前11-20個數:

>>> L[10:20]
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

前10個數,每兩個取一個:(不是隔2個取一個)

>>> L[:10:2]
[0, 2, 4, 6, 8]

所有數,每5個取一個:

>>> L[::5]
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]

甚至什麼都不寫,只寫[:]就可以原樣複製一個list:

>>> L[:]
[0, 1, 2, 3, ..., 99]

例三

tuple也是一種list,唯一區別是tuple不可變。因此,tuple也可以用切片操作,只是操作的結果仍是tuple:

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

例四

字串’xxx’也可以看成是一種list,每個元素就是一個字元。因此,字串也可以用切片操作,只是操作結果仍是字串:

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

迭代

通過for迴圈來遍歷整個list或tuple或其它,這種遍歷我們稱為迭代(Iteration)。

判斷一個東西是否能迭代

通過collections模組的Iterable型別判斷:

>>> from collections import Iterable
>>> isinstance('abc', Iterable) # str是否可迭代
True
>>> isinstance([1,2,3], Iterable) # list是否可迭代
True
>>> isinstance(123, Iterable) # 整數是否可迭代
False

dict中的迭代

>>> d = {'a': 1, 'b': 2, 'c': 3}
>>> for key in d:
...     print(key)
...
a
c
b

因為dict的儲存不是按照list的方式順序排列,所以,迭代出的結果順序很可能不一樣
預設情況下,dict迭代的是key。如果要迭代value,可以用for value in d.values(),如果要同時迭代key和value,可以用for k, v in d.items()

多輸出迭代

Python內建的enumerate函式可以把一個list變成索引-元素對,這樣就可以在for迴圈中同時迭代索引和元素本身:

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

同時引用了兩個變數,在Python裡是很常見的,比如下面的程式碼:

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

列表生成式

老厲害了

格式

[這裡為表內容的計算格式 for xxx in xxx(範圍) (可以多重迴圈)這裡是表的內容的判斷,符合條件的才會被新增到表內 ]

範例

列表生成式則可以用一行語句代替迴圈生成list:

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

for迴圈後面還可以加上if判斷,這樣我們就可以篩選出僅偶數的平方:

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

還可以使用兩層迴圈,可以生成全排列:

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

三層和三層以上的迴圈就很少用到了。
for迴圈其實可以同時使用兩個甚至多個變數,比如dict的items()可以同時迭代key和value:

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

因此,列表生成式也可以使用兩個變數來生成list:

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

這裡+似乎是連線符,而不是加號

L3=[x + x for x in range(1, 11)]
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

測試出來是加號
str和int一起用加號會報錯,想了想也沒問題。。。

生成器generator

通過列表生成式,我們可以直接建立一個列表。但是,受到記憶體限制,列表容量肯定是有限的。而且,建立一個包含100萬個元素的列表,不僅佔用很大的儲存空間,如果我們僅僅需要訪問前面幾個元素,那後面絕大多數元素佔用的空間都白白浪費了。

所以,如果列表元素可以按照某種演算法推算出來,那我們是否可以在迴圈的過程中不斷推算出後續的元素呢?這樣就不必建立完整的list,從而節省大量的空間。在Python中,這種一邊迴圈一邊計算的機制,稱為生成器:generator。

要建立一個generator,有很多種方法。第一種方法很簡單,只要把一個列表生成式的[]改成(),就建立了一個
generator儲存的是演算法,每次呼叫next(g),就計算出g的下一個元素的值,直到計算到最後一個元素,沒有更多的元素時,丟擲StopIteration的錯誤。

當然,上面這種不斷呼叫next(g)實在是太變態了,正確的方法是使用for迴圈,因為generator也是可迭代物件
所以,我們建立了一個generator後,基本上永遠不會呼叫next(),而是通過for迴圈來迭代它,並且不需要關心StopIteration的錯誤。

generator非常強大。如果推算的演算法比較複雜,用類似列表生成式的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'

注意,賦值語句:

a, b = b, a + b
相當於:

t = (b, a + b) # t是一個tuple
a = t[0]
b = t[1]
但不必顯式寫出臨時變數t就可以賦值。(看起來就是a=b,b=a+b 的簡寫?)
定義generator的另一種方法。如果一個函式定義中包含yield關鍵字,那麼這個函式就不再是一個普通函式,而是一個generator:

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

generator和函式的執行流程不一樣。函式是順序執行,遇到return語句或者最後一行函式語句就返回。而變成generator的函式,在每次呼叫next()的時候執行,遇到yield語句返回,再次執行時從上次返回的yield語句處繼續執行。

練習

楊輝三角定義如下:

          1
        1   1
      1   2   1
    1   3   3   1
  1   4   6   4   1
1   5   10  10  5   1

把每一行看做一個list,試寫一個generator,不斷輸出下一行的list:

# -*- coding: utf-8 -*-
???

n = 0
for t in triangles():
    print(t)
    n = n + 1
    if n == 10:
        break

解題經過

不得不承認構思了許久還是沒有想出來。
邏輯都沒有整理出來怎麼寫程式碼
最開始寫的程式碼

def triangles():
    L = [1]
    while True:
        yield L
        L = [L[i - 1] + L[i] for i in range(len(L))]

while True最開始還忘加冒號了。輸出根本不對,本來還擔心如果沒有怎麼辦,報錯?哦,python裡有L[-1]這種存在,結果變成一個單純的翻倍函數了。才注意到這樣子L根本不會變長啊,於是改成這樣了:
L = [L[i - 1] + L[i] for i in range((len(L)+1))]
結果報出超出長度了,和c區別不少嘛(雖然c也不能這樣延長吧,但至少不會報錯的)。思考了以下,找了一下延長函式append,繼續研究
其實當時挺接近結果了,結果我換了個方式寫

def triangles():
    L= [1]
    while True:
        yield ret
        for i in range(1, len(L)):
            L[i] = L[i] + L[i - 1]
        L.append(1)

為了讓第一個數不便還特意讓它從1開始的,結果就只能對3行
經過多次驗證,終於發現它是實時更新的L[i] = L[i] + L[i - 1],L[i-1]已經是最新的了,那就建一個序列來儲存之前的。

def triangles():
    L= [1]
    while True:
        yield L
        L1 = L
        for i in range(1,len(L)):
            L[i] = L1[i] + L1[i - 1]
        L.append(1)

結果L1和L是一個序列啊,L更新它也跟著更新啊,你們兩指標是不是指一起去了啊。
又研究一下怎麼複製表,終於完成

def triangles():
    L= [1]
    while True:
        yield L
        L1 = L.copy()
        for i in range(1,len(L)):
            L[i] = L1[i] + L1[i - 1]
        L.append(1)

答案

#方法一
def triangles():
    L = [1]
    while True:
        yield L
        L.append(0)
        L = [L[i - 1] + L[i] for i in range(len(L))]

#方法二
def triangles():
    ret = [1]
    while True:
        yield ret
        for i in range(1, len(ret)):
            ret[i] = pre[i] + pre[i - 1]
        ret.append(1)
        pre = ret[:]

我的方法可以說就是第二種(原來這樣就能複製List了啊)。看了看第一種, L = [L[i - 1] + L[i] for i in range(len(L))],難道L[i]就不受L[i-1]的影響了嗎?對的,不受。為什麼倒是不清楚。。。。莫非不是逐項取代,而是生成新表刪除舊錶嘍。原來還有最後補個0 這種操作的。
還差的遠了

迭代器

我們已經知道,可以直接作用於for迴圈的資料型別有以下幾種:

一類是集合資料型別,如list、tuple、dict、set、str等;

一類是generator,包括生成器和帶yield的generator function。

這些可以直接作用於for迴圈的物件統稱為可迭代物件:Iterable

可以使用isinstance()判斷一個物件是否是Iterable物件:
isinstance({}, Iterable)
而生成器不但可以作用於for迴圈,還可以被next()函式不斷呼叫並返回下一個值,直到最後丟擲StopIteration錯誤表示無法繼續返回下一個值了。
可以被next()函式呼叫並不斷返回下一個值的物件稱為迭代器:Iterator
可以使用isinstance()判斷一個物件是否是Iterator物件
isinstance([], Iterator)
生成器都是Iterator物件,但list、dict、str雖然是Iterable,卻不是Iterator。
Iterator,也就是一個惰性序列,所以要強迫filter()完成計算結果,需要用list()函式獲得所有結果並返回list。不然它會等到你要結果的時候才算
把list、dict、str等Iterable變成Iterator可以使用iter()函式

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

凡是可作用於for迴圈的物件都是Iterable型別;

凡是可作用於next()函式的物件都是Iterator型別,它們表示一個惰性計算的序列;

集合資料型別如list、dict、str等是Iterable但不是Iterator,不過可以通過iter()函式獲得一個Iterator物件。

Python的for迴圈本質上就是通過不斷呼叫next()函式實現的

相關推薦

python學習8——高階特性

高階特性 切片(關於list和tuple的操作) 可以將list和tuple甚至於字串的選擇性輸出 標準格式 L[(這裡填入選數的開始序號):(這裡填入選數的結束序號): (這裡填入每幾個數選取一個數) ] 結束序號所在的資料不會被輸出

Python學習3——高階特性

1、切片 (1)後10個數:L[-10:] (2)前10個數,每兩個取一個:L[:10:2] (3)倒序:L[::-1] https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542

python學習8實例:寫一個簡單商城購物車的代碼

商品 流程圖 index blog pen 什麽 author 數字 git 要求: 1、寫一段商城程購物車序的代碼2、用列表把商城的商品清單存儲下來,存到列表 shopping_mail3、購物車的列表為shopping_cart4、用戶首先輸入工資金額,判斷輸入為數字5

python學習8

== The lse 遍歷 while ber pass 學習 數字 退出雙層循環:方式1:try--except try: for i in range(5): for j in range(5): if i==3 and

Python學習8——錯誤、除錯和測試

1、錯誤處理 (1)常見的錯誤型別和繼承關係看這裡: https://docs.python.org/3/library/exceptions.html#exception-hierarchy (2)如果錯誤沒有被捕獲,它就會一直往上拋,最後被Python直譯器捕獲,列印一個錯誤資訊

廖雪峰的python筆記--高階特性

目錄 1.切片: 2.迭代:通過for迴圈來遍歷這個list或tuple 3.列表生成式:List Comprehensions--用來建立list的生成式。 4.生成器: 5.迭代器: 程式碼越簡單越好! 1.切片: 取一個list或tuple的部分元素是

Python學習8——IO程式設計

1、檔案讀寫 (1)由於檔案讀寫時都有可能產生IOError,一旦出錯,後面的f.close()就不會呼叫。所以,為了保證無論是否出錯都能正確地關閉檔案,我們可以使用try ... finally來實

python學習筆記---高階特性

#!/usr/bin/env python3 # -*- coding: utf-8 -*- r''' 高階知識 lrn_higher_list: 切片、迭代、列表生成式、生成器、迭代器 lrn_higher_func: 函數語言程

Python學習筆記——高階特性

1, 1, 2, 3, 5, 8, 13, 21, 34, ... 斐波拉契數列用列表生成式寫不出來,但是,用函式把它打印出來卻很容易: def fib(max): n, a, b = 0, 0, 1 while n < max: print(b)

python學習筆記7-高階特性-列表生成式與生成器

 [d for d in os.listdir('.')] ['.bash_logout', '.bash_profile', '.bashrc', '.cshrc', '.tcshrc', 'anaconda-ks.cfg', '.cache', '.config', 'perl5', '.bash_hi

Redis學習8-redis其他特性

font 提前 redis學習 清空 exec 自己 mysql數據庫 data 批量執行 消息訂閱與發布 subscribe  Channel:訂閱頻道 psubscribe  channel*:批量訂閱頻道:例如:psubscribe  S*,訂閱以S開頭的頻道。 pu

Python學習7——面向物件高階編輯

1、使用__slots__ (1)可以嘗試給例項繫結一個方法: def set_age(self, age): self.age = age from types import MethodType s.set_age = MethodType(set_age, s) # 給例項

Python基礎8python中的特性進階篇迭代,列表生成式,生成器,迭代器

python中還包括一些高階特性,以下簡單介紹。 迭代 定義:用for迴圈來遍歷物件的過程,叫做迭代。 作用物件:可迭代物件 如何判斷是否為可迭代物件:isinstance(xxx,Iterable),Iterable型別來源於collections模組。 應用場景: 1

重拾Python學習----------面向物件高階程式設計

本文參考:廖雪峰的官方網站:https://www.liaoxuefeng.com 使用__slots__ 果我們想要限制例項的屬性,比如,只允許對Student例項新增name和age屬性。 class Student(object): __slots

Python4高階特性 總結

  Python中很多常見語法可以使程式更加簡潔易讀,這裡我們介紹5個例子:切片、迭代、列表生成器、生成器、迭代器 1.切片(slice) 切片用於取list tuple中部分元素,通過下標索引,只需標出想得到的第一個元素下標和最後一個元素 L[a:b] 從

python2.7學習筆記6 ——高階特性:切片、迭代、列表生成式、生成器

切片 用於擷取list中的元素,比如L是一個list L[a : b] a 迭代 如果給定一個list或tuple,我們可以通過for迴圈來遍歷這個list或tuple,這種遍歷我們稱為迭代(Iteration)。 只要是可迭代物件,無論有無下

Python學習

ubun 安裝目錄 tle setup extract reat 常用插件 增加 網址 Python學習(一) 一:開發工具安裝   1,pycharm下載:Linux版本   2,破解:在help-register下-service輸入:      http://elpo

PYTHON學習之利用python進行數據分析(1)---準備工作

-- 下載 rip 安裝包 png 要求 eight code 電腦   學習一門語言就是不斷實踐,python是目前用於數據分析最流行的語言,我最近買了本書《利用python進行數據分析》(Wes McKinney著),還去圖書館借了本《Python數據分析基礎教程--N

Python學習 八大排序算法的實現

ram tty adjust 二叉樹 turn bre python 使用 元素 本文Python實現了插入排序、基數排序、希爾排序、冒泡排序、高速排序、直接選擇排序、堆排序、歸並排序的後面四種。 上篇:Python學習(三) 八大排序算法的實現(上)

Shiro學習8攔截器機制

綁定 local cin 沒有 代碼 authz https 字符串 subject 8.1 攔截器介紹 Shiro使用了與Servlet一樣的Filter接口進行擴展;所以如果對Filter不熟悉可以參考《Servlet3.1規範》http://www.iteye.com