重新學習python系列(一)? WTF?
重新學習python:
兩年前學了點python之後就一直沒做做過啥項目, 基本上全忘光了,復習一下搞點事情
or |
and &
ord() ascii轉16進制
chr() 16進制轉ascii
>>> u‘ABC‘.encode(‘utf-8‘) ‘ABC‘ >>> u‘中文‘.encode(‘utf-8‘) ‘\xe4\xb8\xad\xe6\x96\x87‘
>>> ‘abc‘.decode(‘utf-8‘) u‘abc‘ >>> ‘\xe4\xb8\xad\xe6\x96\x87‘.decode(‘utf-8‘) u‘\u4e2d\u6587‘ >>> print ‘\xe4\xb8\xad\xe6\x96\x87‘.decode(‘utf-8‘) 中文
數組list:
append(‘a‘) 插到後面
insert(1,‘a‘) 指定位置
pop() 刪除末尾 刪除指定
元組tuple:
只有1個元素的tuple定義時必須加一個逗號,
,來消除歧義:
>>> t = (1,) >>> t (1,)
“可變的”tuple:t = (‘a‘, ‘b‘, [‘A‘, ‘B‘])
dict:key-value存儲方式
通過in
判斷key是否存在:
iteritems
>>> ‘Thomas‘ in d False
通過dict提供的get方法:如果key不存在,可以返回None,或者自己指定的value(不改變dict)
dict = { ‘a‘ : "this a", ‘b‘ : "this b", ‘c‘ : "this c", ‘d‘ : "this d" } print dict.get(‘f‘,"hello") print dict hello {‘a‘: ‘this a‘, ‘c‘: ‘this c‘, ‘b‘: ‘this b‘, ‘d‘: ‘this d‘}
用pop(key)
方法,對應的value也會從dict中刪除
和list比較,dict有以下幾個特點:
- 查找和插入的速度極快,不會隨著key的增加而增加;
- 需要占用大量的內存,內存浪費多。
而list相反:
- 查找和插入的時間隨著元素的增加而增加;
- 占用空間小,浪費內存很少
set:一組key的集合,但不存儲value。由於key不能重復,所以,在set中,沒有重復的key。
通過add(key)
方法可以添加元素到set中,可以重復添加,但不會有效果
通過remove(key)
方法可以刪除元素:
>>> s1 = set([1, 2, 3]) >>> s2 = set([2, 3, 4]) >>> s1 & s2 set([2, 3]) >>> s1 | s2 set([1, 2, 3, 4])
再議不可變對象 上面我們講了,str是不變對象,而list是可變對象。 對於可變對象,比如list,對list進行操作,list內部的內容是會變化的,比如: >>> a = [‘c‘, ‘b‘, ‘a‘] >>> a.sort() >>> a [‘a‘, ‘b‘, ‘c‘] 而對於不可變對象,比如str,對str進行操作呢: >>> a = ‘abc‘ >>> a.replace(‘a‘, ‘A‘) ‘Abc‘ >>> a ‘abc‘ 雖然字符串有個replace()方法,也確實變出了‘Abc‘,但變量a最後仍是‘abc‘,應該怎麽理解呢? 我們先把代碼改成下面這樣: >>> a = ‘abc‘ >>> b = a.replace(‘a‘, ‘A‘) >>> b ‘Abc‘ >>> a ‘abc‘ 要始終牢記的是,a是變量,而‘abc‘才是字符串對象!有些時候,我們經常說,對象a的內容是‘abc‘,但其實是指,a本身是一個變量,它指向的對象的內容才是‘abc‘:
調用函數
http://docs.python.org/2/library/functions.html#abs
如何判斷一個對象是可叠代對象呢?方法是通過collections模塊的Iterable類型判斷:
>>> from collections import Iterable >>> isinstance(‘abc‘, Iterable) # str是否可叠代 True >>> isinstance([1,2,3], Iterable) # list是否可叠代 True >>> isinstance(123, Iterable) # 整數是否可叠代 False
Python內置的enumerate
函數可以把一個list變成索引-元素對
>>> for i, value in enumerate([‘A‘, ‘B‘, ‘C‘]): ... print i, value ... 0 A 1 B 2 C
>>> for x, y in [(1, 1), (2, 4), (3, 9)]: ... print x, y ... 1 1 2 4 3 9
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:
>>> [x * x for x in range(1, 11)] [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>> [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‘]
>>> 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‘]
list中所有的字符串變成小寫:
list.lower()
>>> L = [‘Hello‘, ‘World‘, ‘IBM‘, ‘Apple‘] >>> [s.lower() for s in L] [‘hello‘, ‘world‘, ‘ibm‘, ‘apple‘]
使用內建的isinstance
函數可以判斷一個變量是不是字符串:
>>> x = ‘abc‘ >>> y = 123 >>> isinstance(x, str) True >>> isinstance(y, str) False
生成器generator: 只要把一個列表生成式的[]
改成()
,就創建了一個generator:
g = (x * x for x in range(10))
用 g.next
() 打印
正確的方法是使用for
循環,因為generator也是可叠代對象
>>> g = (x * x for x in range(10)) >>> for n in g: ... print n ... 0 1 4 9
把print b
改為yield b
就可以變成生成器generator:
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b #print b
a, b = b, a + b
n = n + 1
這就是定義generator的另一種方法。如果一個函數定義中包含yield關鍵字,那麽這個函數就不再是一個普通函數,而是一個generator: >>> fib(6) <generator object fib at 0x104feaaa0> 這裏,最難理解的就是generator和函數的執行流程不一樣。函數是順序執行,遇到return語句或者最後一行函數語句就返回。而變成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 ... >>> o = odd() >>> o.next() step 1 1 >>> o.next() step 2 3 >>> o.next() step 3 5 >>> o.next() Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration 可以看到,odd不是普通函數,而是generator,在執行過程中,遇到yield就中斷,下次又繼續執行。執行3次yield後,已經沒有yield可以執行了,所以,第4次調用next()就報錯。 回到fib的例子,我們在循環過程中不斷調用yield,就會不斷中斷。當然要給循環設置一個條件來退出循環,不然就會產生一個無限數列出來。 同樣的,把函數改成generator後,我們基本上從來不會用next()來調用它,而是直接使用for循環來叠代: >>> for n in fib(6): ... print n ... 1 1 2 3 5 8
map()
>>> def f(x): ... return x * x ... >>> map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]) [1, 4, 9, 16, 25, 36, 49, 64, 81]
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
>>> def add(x, y): ... return x + y ... >>> reduce(add, [1, 3, 5, 7, 9]) 25
upper()——所有字母大寫
lower()——所有字母小寫
capitalize()——首字母大寫,其他字母小寫
title()——所有單詞首字母大寫,其他小寫
filter()
把傳入的函數依次作用於每個元素,然後根據返回值是True
還是False
決定保留還是丟棄該元素
def is_odd(n): return n % 2 == 1 filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]) # 結果: [1, 5, 9, 15]
Python內置的sorted()
函數就可以對list進行排序:
它還可以接收一個比較函數來實現自定義的排序。比如,如果要倒序排序,我們就可以自定義一個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]
忽略大小寫來比較兩個字符串,實際上就是先把字符串都變成大寫(或者都變成小寫),再比較。
返回閉包時牢記的一點就是:返回函數不要引用任何循環變量,或者後續會發生變化的變量。
閉包 註意到返回的函數在其定義內部引用了局部變量args,所以,當一個函數返回了一個函數後,其內部的局部變量還被新函數引用,所以,閉包用起來簡單,實現起來可不容易。 另一個需要註意的問題是,返回的函數並沒有立刻執行,而是直到調用了f()才執行。我們來看一個例子: def count(): fs = [] for i in range(1, 4): def f(): return i*i fs.append(f) return fs f1, f2, f3 = count() 在上面的例子中,每次循環,都創建了一個新的函數,然後,把創建的3個函數都返回了。 你可能認為調用f1(),f2()和f3()結果應該是1,4,9,但實際結果是: >>> f1() 9 >>> f2() 9 >>> f3() 9
匿名函數lambda x: x * x
實際上就是:
def f(x):
return x * x
裝飾器:
def log(func): def wrapper(*args, **kw): print ‘call %s():‘ % func.__name__ return func(*args, **kw) return wrapper
@log
def now():
print ‘2013-12-25
now()
把@log
放到now()
函數的定義處,相當於執行了語句:now = log(now)
偏函數
import functools def func(x,y): print x+y func2 = functools.partial(func, y=‘fuck‘) func2("hello ")
模塊別名:
try: import cStringIO as StringIO except ImportError: # 導入失敗會捕獲到ImportError import StringIO
重新學習python系列(一)? WTF?