1. 程式人生 > >Python之學習筆記(高階特性)

Python之學習筆記(高階特性)

[TOC]
切片,迭代,列表表示式,生成器

高階特性

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

from collections import Iterable

L = []
n = 1
while n <= 99:
    L.append(n)
    n = n + 2
#print L

#切片操作
L = range(100)
#print L[1:20]  #和Matlab一樣
'''
前10個數,每兩個取一個:
>>> 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] '''
#迭代操作:就是迴圈而已 #print isinstance(123, Iterable) ''' dict迭代的是key。如果要迭代value,可以用for value in d.itervalues(),如果要同時迭代key和value,可以用for k, v in d.iteritems()。 進行下標和資料同時迭代: >>> for i, value in enumerate(['A', 'B', 'C']): ... print i, value ... 0 A 1 B 2 C 判斷某種資料型別是不是可以迭代 >>>
from collections import Iterable >>> isinstance('abc', Iterable) # str是否可迭代 True >>> isinstance([1,2,3], Iterable) # list是否可迭代 True >>> isinstance(123, Iterable) # 整數是否可迭代 False 引用了兩個變數 >>> for x, y in [(1, 1), (2, 4), (3, 9)]: ... print x, y ... 1 1 2 4 3 9 '''
#列表生成器 ''' 1、 >>> [x * x for x in range(1, 11)] [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 2、 >>> [x * x for x in range(1, 11) if x % 2 == 0] [4, 16, 36, 64, 100] 3、全排列 可以使用兩層迴圈,可以生成全排列: >>> [m + n for m in 'ABC' for n in 'XYZ'] ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ'] 4、顯示目錄名 >>> import os # 匯入os模組,模組的概念後面講到 >>> [d for d in os.listdir('.')] # os.listdir可以列出檔案和目錄 ['.emacs.d', '.ssh', '.Trash', 'Adlm', 'Applications', 'Desktop', 'Documents', 'Downloads', 'Library', 'Movies', 'Music', 'Pictures', 'Public', 'VirtualBox VMs', 'Workspace', 'XCode'] 5、for迴圈其實可以同時使用兩個甚至多個變數,比如dict的iteritems()可以同時迭代key和value: >>> d = {'x': 'A', 'y': 'B', 'z': 'C' } >>> for k, v in d.iteritems(): ... print k, '=', v ... y = B x = A z = C 列表生成式也可以使用兩個變數來生成list: >>> d = {'x': 'A', 'y': 'B', 'z': 'C' } >>> [k + '=' + v for k, v in d.iteritems()] ['y=B', 'x=A', 'z=C'] 最後把一個list中所有的字串變成小寫: >>> L = ['Hello', 'World', 'IBM', 'Apple'] >>> [s.lower() for s in L] ['hello', 'world', 'ibm', 'apple'] 思考:如果list中既包含字串,又包含整數,由於非字串型別沒有lower()方法,所以列表生成式會報錯: >>> L = ['Hello', 'World', 18, 'Apple', None] >>> [s.lower() for s in L] Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'int' object has no attribute 'lower' 使用內建的isinstance函式可以判斷一個變數是不是字串: >>> x = 'abc' >>> y = 123 >>> isinstance(x, str) True >>> isinstance(y, str) False 請修改列表生成式,通過新增if語句保證列表生成式能正確地執行。 ''' #生成器(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 0x104feab40> 建立L和g的區別僅在於最外層的[]和(),L是一個list,而g是一個generator。 我們可以直接打印出list的每一個元素,但我們怎麼打印出generator的每一個元素呢? 如果要一個一個打印出來,可以通過generator的next()方法: >>> g = (x * x for x in range(10)) >>> for n in g: ... print n 第二種方法:最難理解的就是generator和函式的執行流程不一樣。函式是順序執行,遇到return語句或者最後一行函式語句就返回。而變成generator的函式,在每次呼叫next()的時候執行, 遇到yield語句返回,再次執行時從上次返回的yield語句處繼續執行。 generator是非常強大的工具,在Python中,可以簡單地把列表生成式改成generator, 也可以通過函式實現複雜邏輯的generator。 要理解generator的工作原理,它是在for迴圈的過程中不斷計算出下一個元素, 並在適當的條件結束for迴圈。對於函式改成的generator來說,遇到return語句或者執行到函式體最後一行語句,就是結束generator的指令,for迴圈隨之結束。 ''' def fib(max): n, a, b = 0, 0, 1 while n < max: yield b a, b = b, a + b n = n + 1 for n in fib(6): print n def f(x): return x*x #print map(f,range(9)) ''' reduce把一個函式作用在一個序列[x1, x2, x3...]上, 這個函式必須接收兩個引數,reduce把結果繼續和序列的下一個元素做累積計算 ''' def add(x,y): return x+y L = range(100) #print reduce(add, L) # 整數和字串的轉換 def chr2num(s): return {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}[s] def fn(x,y): return 10*x+y #print map(chr2num,'12345') #print reduce(fn,map(chr2num,'12345')) def str2int(s): def fn(x, y): return x * 10 + y def char2num(s): return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s] return reduce(fn, map(char2num, s)) L = range(100) def get_list(x,y): L = [] n = 0 while n < y: L.append(x) n = n + 1 return L #print get_list(3) def prod2(x,y): return sum(get_list(x,y)) #print prod2(2,3) def prod(*s): return reduce(prod2,s) L = range(100) L1 = L[1:6] #print prod(*L1) #首字母大寫 def get_right_name1(x): return x.capitalize() def get_right_name2(x): return x.title() def get_right_name2(x): return x.title() def get_right_name3(x): y = x.lower() y = y[0].upper() + y[1:] return y #print map(get_right_name3,['HHHHHHH']) #這裡需要寫成列表,因為'HHHH'在map下會一個個被取出 #排序 ''' sorted()函式就可以對list進行排序: >>> sorted([36, 5, 12, 9, 21]) [5, 9, 12, 21, 36] sorted()函式也是一個高階函式,它還可以接收一個比較函式來實現自定義的排序。 比如,如果要倒序排序,我們就可以自定義一個reversed_cmp函式 def reversed_cmp(x, y): if x > y: return -1 if x < y: return 1 return 0 傳入自定義的比較函式reversed_cmp,就可以實現倒序排序: >>> sorted([36, 5, 12, 9, 21], reversed_cmp) [36, 21, 12, 9, 5] 我們再看一個字串排序的例子: >>> sorted(['bob', 'about', 'Zoo', 'Credit']) ['Credit', 'Zoo', 'about', 'bob'] 預設情況下,對字串排序,是按照ASCII的大小比較的,由於'Z' < 'a',結果,大寫字母Z會排在小寫字母a的前面。 現在,我們提出排序應該忽略大小寫,按照字母序排序。要實現這個演算法,不必對現有程式碼大加改動, 只要我們能定義出忽略大小寫的比較演算法就可以: ''' def ignore_upper(s1,s2): u1 = s1.lower() u2 = s2.lower() if u1 > u2: return 1 elif u1 < u2: return -1 else: return 0 #print sorted(['Za','a','dff'],ignore_upper) # filter函式的使用 # 和map()類似,filter()也接收一個函式和一個序列。和map()不同的時,filter()把傳入的函式依次作用於每個元素, # 然後根據返回值是True還是False決定保留還是丟棄該元素。 # 可見用filter()這個高階函式,關鍵在於正確實現一個“篩選”函式。 # filter函式有一個過濾函式,滿足這個條件的話就留住 def is_sushu(x): L = range(x) if x > 2: for n in L[2:x]: if x%n == 0: return True else: pass elif x == 2: return False else: return True return False L = range(101) #print filter(is_sushu,L[1:101])