工具學(xué)習(xí) -python -01 基礎(chǔ)知識點

借著別人的文章(王圣元 [王的機器] )终吼,復(fù)盤一下python的基礎(chǔ)知識點。感謝原作者的分享氯哮!

一际跪、基本數(shù)據(jù)類型:整數(shù),浮點數(shù)喉钢,布爾
二姆打、容器數(shù)據(jù)類型:字符,元組肠虽,列表幔戏,字典,集合
三税课、條件語句和迭代循環(huán):If, If_else, Nested, While, For
四闲延、函數(shù):正規(guī)函數(shù),匿名函數(shù)韩玩,偏函數(shù)垒玲,柯里化
五、解析式:列表找颓,字典合愈,集合解析

對于任何一種計算機語言,我覺得最重要的就是「數(shù)據(jù)類型」「條件語句 & 迭代循環(huán)」和「函數(shù)」叮雳,這三方面一定要打牢基礎(chǔ)想暗。此外 Python 非常簡潔妇汗,一行代碼 (one-liner) 就能做很多事情帘不,很多時候都用了各種「解析式」,比如列表杨箭、字典和集合解析式寞焙。

在學(xué)習(xí)本貼前感受一下這個問題:如何把以下這個不規(guī)則的列表 a 里的所有元素一個個寫好,專業(yè)術(shù)語叫打平 (flatten)?

a = [1, 2, [3, 4], [[5, 6], [7, 8]]]

魔法來了 (這一行代碼有些長,用手機的建議橫屏看)

fn = lambda x: [y for l in x for y in fn(l)] if type(x) is list else [x]
[1, 2, 3, 4, 5, 6, 7, 8]

這一行代碼捣郊,用到了迭代辽狈、匿名函數(shù)、遞推函數(shù)呛牲、解析式這些技巧刮萌。初學(xué)者一看只會說“好酷啊,但看不懂”娘扩,看完本帖和下帖后着茸,我保證你會說“我也會這樣用了,真酷琐旁!


1基本數(shù)據(jù)類型

Python 里面有自己的內(nèi)置數(shù)據(jù)類型 (build-in data type)涮阔,本節(jié)介紹基本的三種,分別是整型 (int)灰殴,浮點型 (float)敬特,和布爾型 (bool)。

1.1 整型

整數(shù) (integer) 是最簡單的數(shù)據(jù)類型牺陶,和下面浮點數(shù)的區(qū)別就是前者小數(shù)點后沒有值伟阔,后者小數(shù)點后有值。例子如下:

a = 1031                 --1031 <class 'int'>

通過 print 的可看出 a 的值掰伸,以及類 (class) 是 int减俏。Python 里面萬物皆對象(object),「整數(shù)」也不例外碱工,只要是對象娃承,就有相應(yīng)的屬性 (attributes) 和方法 (methods)。

知識點

通過 dir( X ) 和help( X ) 可看出 X 對應(yīng)的對象里可用的屬性和方法怕篷。

  • X 是 int历筝,那么就是 int 的屬性和方法
  • X 是 float,那么就是 float 的屬性和方法
dir(int)
['__abs__','__add__',...'__xor__','bit_length','conjugate',...'real','to_bytes']

紅色的是 int 對象的可用方法廊谓,藍(lán)色的是 int 對象的可用屬性梳猪。對他們你有個大概印象就可以了,具體怎么用蒸痹,需要哪些參數(shù) (argument)春弥,你還需要查文檔〉看個bit_length的例子

a.bit_length()              -- 11

該函數(shù)是找到一個整數(shù)的二進(jìn)制表示匿沛,再返回其長度。在本例中 a = 1031, 其二進(jìn)制表示為 ‘10000000111’ 榛鼎,長度為 11逃呼。

1.2 浮點型

簡單來說鳖孤,浮點型 (float) 數(shù)就是實數(shù), 例子如下:

print( 1, type(1) )                 -- 1 <class 'int'>1.0 <class 'float'>

加一個小數(shù)點 . 就可以創(chuàng)建 float抡笼,不能再簡單苏揣。有時候我們想保留浮點型的小數(shù)點后 n 位⊥埔觯可以用 decimal 包里的 Decimal 對象和 getcontext() 方法來實現(xiàn)平匈。

import decimal

Python 里面有很多用途廣泛的包 (package),用什么你就引進(jìn) (import) 什么藏古。包也是對象吐葱,也可以用上面提到的dir(decimal) 來看其屬性和方法。比如 getcontext() 顯示了 Decimal 對象的默認(rèn)精度值是 28 位 (prec=28)校翔,展示如下:

decimal.getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999,Emax=999999, capitals=1, clamp=0, flags=[],traps=[InvalidOperation, DivisionByZero, Overflow])

讓我們看看 1/3 的保留 28 位長什么樣弟跑?

d = Decimal(1) / Decimal(3)
Decimal('0.3333333333333333333333333333')

那保留 4 位呢?用 getcontext().prec 來調(diào)整精度哦防症。

decimal.getcontext().prec = 4 
Decimal('0.3333')

高精度的 float 加上低精度的 float孟辑,保持了高精度,沒毛病蔫敲。

d + e
Decimal('0.6666333333333333333333333333')

1.3 布爾型

布爾 (boolean) 型變量只能取兩個值饲嗽,**True **和 False。當(dāng)把布爾變量用在數(shù)字運算中奈嘿,用 1 和 0 代表 **True **和 False貌虾。

T = True
F = False
print( T + 2 )                      -- 3
print( F - 8 )                      --7

除了直接給變量賦值 **True **和 False,還可以用 bool(X) 來創(chuàng)建變量裙犹,其中 X 可以是

  • 基本類型:整型尽狠、浮點型、布爾型

  • 容器類型:字符叶圃、元組袄膏、列表、字典和集合

基本類型

print( type(0), bool(0), bool(1) )                       --<class 'int'> False True
print( type(10.31), bool(0.00), bool(10.31) )            --<class 'float'> False True
print( type(True), bool(False), bool(True) )             --<class 'bool'> False True

bool 作用在基本類型變量的總結(jié):X 只要不是整型 0掺冠、浮點型 0.0沉馆,bool(X) 就是 True,其余就是 False德崭。

容器類型

print( type(''), bool( '' ), bool( 'python' ) )                --<class 'str'> False True
print( type(()), bool( () ), bool( (10,) ) )                   --<class 'tuple'> False True
print( type([]), bool( [] ), bool( [1,2] ) )                   --<class 'list'> False True
print( type({}), bool( {} ), bool( {'a':1, 'b':2} ) )          --<class 'dict'> False True
print( type(set()), bool( set() ), bool( {1,2} ) )             --<class 'set'> False True

bool 作用在容器類型變量的總結(jié)X 只要不是空的變量斥黑,bool(X) 就是 True,其余就是 False眉厨。

知識點

確定bool(X) 的值是 True 還是 False锌奴,就看 X 是不是空,空的話就是 False缺猛,不空的話就是True缨叫。

  • 對于數(shù)值變量,0, 0.0 都可認(rèn)為是空的荔燎。
  • 對于容器變量耻姥,里面沒元素就是空的。

2 容器數(shù)據(jù)類型

上節(jié)介紹的整型有咨、浮點型和布爾型都可以看成是單獨數(shù)據(jù)琐簇,而這些數(shù)據(jù)都可以放在一個容器里得到一個「容器類型」的數(shù)據(jù),比如:

  • 字符 (str) 是一容器的字節(jié) char座享,注意 Python 里面沒有 char 類型的數(shù)據(jù)婉商,可以把單字符的 str 當(dāng)做 char。
  • 元組 (tuple)渣叛、列表 (list)丈秩、字典 (dict) 和集合 (set) 是一容器的任何類型變量。

2.1 字符

字符用于處理文本 (text) 數(shù)據(jù)淳衙,用「單引號 ’」和「雙引號 “」來定義都可以蘑秽。
創(chuàng)建字符

t1 = 'i love Python!'
print( t1, type(t1) )             --i love Python! <class 'str'>
t2 = "I love Python!"
print( t2, type(t2) )             --I love Python! <class 'str'>

字符中常見的內(nèi)置方法 (可以用 dir(str) 來查) 有

  • capitalize():大寫句首的字母
  • split():把句子分成單詞
  • find(x):找到給定詞 x 在句中的索引,找不到返回 -1
  • replace(x, y):把句中 x 替代成 y
  • strip(x):刪除句首或句末含 x 的部分
t1.capitalize()                                      --'I love python!'
t2.split()                                           --['I', 'love', 'Python!']
print( t1.find('love') )                             -- 2
print( t1.find('like') )                             -- 1
t2.replace( 'love Python', 'hate R' )                --'I hate R!'
print( 'http://www.python.org'.strip('htp:/') )      --www.python.org
print( 'http://www.python.org'.strip('.org') )       --http://www.python

索引和切片

s = 'Python'
print( s )                   --Python           
print( s[2:4] )              --th
print( s[-5:-2] )            --yth
print( s[2] )                --t
print( s[-1] )               --n

知識點

Python 里面索引有三個特點 (經(jīng)常讓人困惑):

  1. 從 0 開始 (和 C 一樣)箫攀,不像 Matlab 從 1 開始肠牲。
  2. 切片通常寫成 start:end 這種形式,包括「start 索引」對應(yīng)的元素靴跛,不包括「end索引」對應(yīng)的元素缀雳。因此 s[2:4] 只獲取字符串第 3 個到第 4 個元素。
  3. 索引值可正可負(fù)梢睛,正索引從 0 開始肥印,從左往右;負(fù)索引從 -1 開始绝葡,從右往左竖独。使用負(fù)數(shù)索引時,會從最后一個元素開始計數(shù)挤牛。最后一個元素的位置編號是 -1莹痢。

正則表達(dá)式

正則表達(dá)式 (regular expression) 主要用于識別字符串中符合某種模式的部分,什么叫模式呢墓赴?用下面一個具體例子來講解竞膳。

input = """
'06/18/2019 13:00:00', 100, '1st';
'06/18/2019 13:30:00', 110, '2nd';
'06/18/2019 14:00:00', 120, '3rd'
"""

假如你想把上面字符串中的「時間」的模式來抽象的表示出來,對照著具體表達(dá)式 '06/18/2019 13:00:00' 來看诫硕,我們發(fā)現(xiàn)該字符串有以下規(guī)則:

  1. 開頭和結(jié)束都有個單引號 '
  2. 里面有多個 0-9 數(shù)字
  3. 里面有多個正斜線 / 和分號 :
  4. 還有一個空格

因此我們用下面這樣的模式

pattern = re.compile("'[0-9/:\s]+'")

再看這個抽象模式表達(dá)式 '[0-9/:\s]+'坦辟,里面符號的意思如下:

  • 最外面的兩個單引號 ' 代表該模式以它們開始和結(jié)束
  • 中括號 [] 用來概括該模式涵蓋的所有類型的字節(jié)
  • 0-9 代表數(shù)字類的字節(jié)
  • / 代表正斜線
  • : 代表分號
  • \s 代表空格
  • [] 外面的加號 + 代表 [] 里面的字節(jié)出現(xiàn)至少 1 次

有了模式 pattern,我們來看看是否能把字符串中所有符合 pattern 的日期表達(dá)式都找出來章办。

pattern.findall(input)
["'06/18/2019 13:00:00'",
 "'06/18/2019 13:30:00'",
 "'06/18/2019 14:00:00'"]

結(jié)果是對的锉走,之后你想怎么盤它就是你自己的事了滨彻,比如把 / 換成 -,比如用 datetime 里面的 striptime() 把日期里年挪蹭、月亭饵、日、小時梁厉、分鐘和秒都獲取出來辜羊。

2.2元組

創(chuàng)建元組

「元組」定義語法為 : (元素1, 元素2, ..., 元素n)
關(guān)鍵點是「小括號 ()」和「逗號 ,」

  • 小括號把所有元素綁在一起
  • 逗號將每個元素一一分開

創(chuàng)建元組的例子如下:

t1 = (1, 10.31, 'python')
t2 = 1, 10.31, 'python'
print( t1, type(t1) )             --(1, 10.31, 'python') <class 'tuple'>
print( t2, type(t2) )             --(1, 10.31, 'python') <class 'tuple'>

知識點

創(chuàng)建元組可以用小括號 (),也可以什么都不用词顾,為了可讀性八秃,建議還是用 ()。此外對于含單個元素的元組肉盹,務(wù)必記住要多加一個逗號昔驱,舉例如下:

print( type( ('OK') ) )                 --<class 'str'>
print( type( ('OK',) )                  --<class 'tuple'>

看看,沒加逗號來創(chuàng)建含單元素的元組上忍,Python 認(rèn)為它是字符舍悯。

當(dāng)然也可以創(chuàng)建二維元組:

nested = (1, 10.31, 'python'), ('data', 11)
nested                                --((1, 10.31, 'python'), ('data', 11))

索引和切片

元組中可以用整數(shù)來對它進(jìn)行索引 (indexing) 和切片 (slicing),不嚴(yán)謹(jǐn)?shù)闹v睡雇,前者是獲取單個元素萌衬,后者是獲取一組元素。接著上面二維元組的例子它抱,先看看索引的代碼:

nested[0]                                               --(1, 10.31, 'python')
print( nested[0][0], nested[0][1], nested[0][2] )       --1 10.31 python    

再看看切片的代碼:

nested[0][0:2]                                           --(1, 10.31)

不可更改
元組有不可更改 (immutable) 的性質(zhì)秕豫,因此不能直接給元組的元素賦值,例子如下 (注意「元組不支持元素賦值」的報錯提示)观蓄。

t = ('OK', [1, 2], True) 
t[2] = False         --TypeError: 'tuple' object does not support item assignment

但是只要元組中的元素可更改 (mutable)混移,那么我們可以直接更改其元素,注意這跟賦值其元素不同侮穿。如下例 t[1] 是列表歌径,其內(nèi)容可以更改,因此用 append 在列表后加一個值沒問題亲茅。

t[1].append(3)             --('OK', [1, 2, 3], True)

內(nèi)置方法

元組大小和內(nèi)容都不可更改回铛,因此只有 count 和 index 兩種方法。

t = (1, 10.31, 'python')
print( t.count('python') )         --1
print( t.index(10.31) )            --1

這兩個方法返回值都是 1克锣,但意思完全不同

  • count('python') 是記錄在元組 t 中該元素出現(xiàn)幾次茵肃,顯然是 1 次
  • index(10.31) 是找到該元素在元組 t 的索引,顯然是 1

元組拼接

元組拼接 (concatenate) 有兩種方式袭祟,用「加號 +」和「乘號 *」验残,前者首尾拼接,后者復(fù)制拼接巾乳。

(1, 10.31, 'python') + ('data', 11) + ('OK',)        --(1, 10.31, 'python', 'data', 11, 'OK')
(1, 10.31, 'python') * 2                   --(1, 10.31, 'python', 1, 10.31, 'python')

解壓元組

解壓 (unpack) 一維元組 (有幾個元素左邊括號定義幾個變量)

t = (1, 10.31, 'python')
(a, b, c) = t
print( a, b, c )                    --1 10.31 python

解壓二維元組 (按照元組里的元組結(jié)構(gòu)來定義變量)

t = (1, 10.31, ('OK','python'))
(a, b, (c,d)) = t
print( a, b, c, d )                 --1 10.31 OK python

如果你只想要元組其中幾個元素您没,用通配符「*」鸟召,英文叫 wildcard,在計算機語言中代表一個或多個元素氨鹏。下例就是把多個元素丟給了 rest 變量欧募。

t = 1, 2, 3, 4, 5
a, b, *rest, c = t
print( a, b, c )                 -- 1 2 5
print( rest )                    --[3, 4]

如果你根本不在乎 rest 變量,那么就用通配符「*」加上下劃線「_」喻犁,劉例子如下:

a, b, *_ = t
print( a, b )                    --1 2

優(yōu)點缺點

優(yōu)點:占內(nèi)存小槽片,安全何缓,創(chuàng)建遍歷速度比列表快肢础,可一賦多值。
缺點:不能添加和更改元素碌廓。

2.3列表

創(chuàng)建列表

「列表」定義語法為 : [元素1, 元素2, ..., 元素n]
關(guān)鍵點是「中括號 []」和「逗號 ,」

  • 中括號把所有元素綁在一起
  • 逗號將每個元素一一分開

創(chuàng)建列表的例子如下:

l = [1, 10.31,'python']
print(l, type(l))                  --[1, 10.31, 'python'] <class 'list'>

內(nèi)置方法

不像元組传轰,列表內(nèi)容可更改 (mutable),因此附加 (append, extend)谷婆、插入 (insert)慨蛙、刪除 (remove, pop) 這些操作都可以用在它身上。

附加


l.append([4, 3])
print( l )                      --[1, 10.31, 'python', [4, 3]]
l.extend([1.5, 2.0, 'OK'])
print( l )                      --[1, 10.31, 'python', [4, 3], 1.5, 2.0, 'OK']

嚴(yán)格來說 append 是追加纪挎,把一個東西整體添加在列表后期贫,而 extend 是擴展,把一個東西里的所有元素添加在列表后异袄。對著上面結(jié)果感受一下區(qū)別通砍。

插入

l.insert(1, 'abc') # insert object before the index position
print(l)           --[1, 'abc', 10.31, 'python', [4, 3], 1.5, 2.0, 'OK']

insert(i, x) 在編號 i 位置前插入 x。對著上面結(jié)果感受一下烤蜕。

刪除

l.remove('python') # remove first occurrence of object
print(I)               --[1, 'abc', 10.31, [4, 3], 1.5, 2.0, 'OK']
p = l.pop(3) # removes and returns object at index.  Only only pop 1 index position at any time.
print( p )               --[4, 3]
print( l )               --[1, 'abc', 10.31, 1.5, 2.0, 'OK']

remove 和 pop 都可以刪除元素

  • 前者是指定具體要刪除的元素封孙,比如 'python'
  • 后者是指定一個編號位置,比如 3讽营,刪除 l[3] 并返回出來

對著上面結(jié)果感受一下虎忌,具體用哪個看你需求。

切片索引

l = [7, 2, 999, 1000, 1, 3, 7, 2, 0, 1]
print( l )                   --[7, 2, 999, 1000, 1, 3, 7, 2, 0, 1]
print( l[1:5:2] )            --[2, 1000]
print( l[:5:2] )             --[7, 999, 1]
print( l[1::2] )             --[2, 1000, 3, 2, 1]
print( l[::2] )              --[7, 999, 1, 7, 0]
print( l[::-1] )             --[1, 0, 2, 7, 3, 1, 1000, 999, 2, 7]

列表拼接

和元組拼接一樣橱鹏, 列表拼接也有兩種方式膜蠢,用「加號 +」和「乘號 *」,前者首尾拼接莉兰,后者復(fù)制拼接狡蝶。

[1, 10.31, 'python'] + ['data', 11] + ['OK']       --[1, 10.31, 'python', 'data', 11, 'OK']
[1, 10.31, 'python'] * 2                           --[1, 10.31, 'python', 1, 10.31, 'python']

優(yōu)點缺點

優(yōu)點:靈活好用,可索引贮勃、可切片贪惹、可更改、可附加寂嘉、可插入奏瞬、可刪除枫绅。
缺點:相比 tuple 創(chuàng)建和遍歷速度慢,占內(nèi)存硼端。此外查找和插入時間較慢并淋。

2.4字典

創(chuàng)建字典

「字典」定義語法為 : {元素1, 元素2, ..., 元素n}
其中每一個元素是一個「鍵值對」- 鍵:值 (key:value)

關(guān)鍵點是「大括號 {}」,「逗號 ,」和「分號 :」

  • 大括號把所有元素綁在一起
  • 逗號將每個鍵值對一一分開
  • 分號將鍵和值分開

創(chuàng)建字典的例子如下:

d = {
'Name' : 'Tencent',
'Country' : 'China',
'Industry' : 'Technology',
'Code': '00700.HK',
'Price' : '361 HKD'
}
print( d, type(d) )    
{'Name': 'Tencent', 'Country': 'China', 
'Industry': 'Technology', 'Code': '00700.HK', 
'Price': '361 HKD'} <class 'dict'>

內(nèi)置方法

字典里最常用的三個內(nèi)置方法就是 keys(), values() 和 items(),分別是獲取字典的鍵珍昨、值县耽、對。

print( list(d.keys()) )        --['Name', 'Country', 'Industry', 'Code', 'Price', 'Headquarter']
print( list(d.values()))       -- ['Tencent', 'China', 'Technology', '00700.HK', '359 HKD', 'Shen Zhen']
print( list(d.items()) )       -- [('Name', 'Tencent'), ('Country', 'China'), ('Industry', 'Technology'), ('Code', '00700.HK'), ('Price', '359 HKD'), ('Headquarter', 'Shen Zhen')]

此外在字典上也有添加镣典、獲取兔毙、更新、刪除等操作兄春。

添加

比如加一個「總部:深圳」

d['Headquarter'] = 'Shen Zhen'
d                                 --{'Name': 'Tencent', 'Country': 'China',
                                     'Industry': 'Technology', 'Code': '00700.HK',
                                     'Price': '361 HKD', 'Headquarter': 'Shen Zhen'}

獲取

比如想看看騰訊的股價是多少 (兩種方法都可以)

print( d['Price'] )          --359 HKD359 HKD

更新

比如更新騰訊的股價到 359 港幣

d['Price'] = '359 HKD'

刪除

比如去掉股票代碼 (code)

del d['Code']

或像列表里的 pop() 函數(shù)澎剥,刪除行業(yè) (industry) 并返回出來。

print( d.pop('Industry') )
d
Technology

{'Name': 'Tencent',
'Country': 'China',
'Price': '359 HKD',
'Headquarter': 'Shen Zhen'}

不可更改鍵

字典里的鍵是不可更改的赶舆,因此只有那些不可更改的數(shù)據(jù)類型才能當(dāng)鍵哑姚,比如整數(shù) (雖然怪怪的)、浮點數(shù) (雖然怪怪的)芜茵、布爾 (雖然怪怪的)叙量、字符、元組 (雖然怪怪的)九串,而列表卻不行绞佩,因為它可更改。

那么如何快速判斷一個數(shù)據(jù)類型 X 是不是可更改的呢蒸辆?兩種方法:

  1. 麻煩方法:用 id(X) 函數(shù)征炼,對 X 進(jìn)行某種操作,比較操作前后的 id躬贡,如果不一樣谆奥,則 X 不可更改,如果一樣拂玻,則 X 可更改酸些。

  2. 便捷方法:用 hash(X),只要不報錯檐蚜,證明 X 可被哈希魄懂,即不可更改,反過來不可被哈希闯第,即可更改市栗。

先看用 id() 函數(shù)的在整數(shù) i 和列表 l 上的運行結(jié)果:


i = 1
print( id(i) )               --1607630928
i = i + 2
print( id(i) )               --1607630992
l = [1, 2]
print( id(l) )               --2022027856840
l.append('Python')
print( id(l) )               --2022027856840
  • 整數(shù) i 在加 1 之后的 id 和之前不一樣,因此加完之后的這個 i (雖然名字沒變),但是不是加前的那個 i 了填帽,因此整數(shù)是不可更改的蛛淋。
  • 列表 l 在附加 'Python' 之后的 id 和之前一樣,因此列表是可更改的篡腌。

先看用 hash() 函數(shù)的在字符 s褐荷,元組 t 和列表 l 上的運行結(jié)果:

hash('Name')                     --7230166658767143139
hash( (1,2,'Python') )           --3642952815031607597
hash( [1,2,'Python'] )           --TypeError: unhashable type: 'list'

字符 s 和元組 t 都能被哈希,因此它們是不可更改的嘹悼。列表 l 不能被哈希叛甫,因此它是可更改的。

優(yōu)點缺點

優(yōu)點:查找和插入速度快
缺點:占內(nèi)存大

2.5集合

創(chuàng)建集合

「集合」有兩種定義語法杨伙,第一種是: {元素1, 元素2, ..., 元素n}
關(guān)鍵點是「大括號 {}」和「逗號 ,」

  • 大括號把所有元素綁在一起
  • 逗號將每個元素一一分開

第二種是用 set() 函數(shù)其监,把列表元組轉(zhuǎn)換成集合。
set( **列表 **或 元組 )

創(chuàng)建集合的例子如下 (用兩者方法創(chuàng)建 A 和 B):

A = set(['u', 'd', 'ud', 'du', 'd', 'du'])
B = {'d', 'dd', 'uu', 'u'}
print( A )                       --{'d', 'du', 'u', 'ud'}
print( B )                       --{'d', 'du', 'u', 'ud'}

從 A 的結(jié)果發(fā)現(xiàn)集合的兩個特點:無序 (unordered) 和唯一 (unique)缀台。由于 set 存儲的是無序集合棠赛,所以我們沒法通過索引來訪問,但是可以判斷一個元素是否在集合中。

B[1]                --TypeError: 'set' object does not support indexing
'u' in B            --True

內(nèi)置方法

用 set 的內(nèi)置方法就把它當(dāng)成是數(shù)學(xué)上的集脏款,那么并集俱笛、交集、差集都可以玩通了审丘。

并集 OR

print( A.union(B) )     # All unique elements in A or B     
--{'uu', 'dd', 'd', 'u', 'du', 'ud'}
print( A | B )          # A OR B                            
--{'uu', 'dd', 'd', 'u', 'du', 'ud'}

交集 AND

print( A.intersection(B) )   # All elements in both A and B
--{'d', 'u'}
print( A & B )               # A AND B
--{'d', 'u'}

差集 A - B

print( A.difference(B) )     # Elements in A but not in B
--{'ud', 'du'}
print( A - B )               # A MINUS B
--{'ud', 'du'}

差集 B - A

print( B.difference(A) )     # Elements in B but not in A
--{'uu', 'dd'}
print( B - A )               # B MINUS A
--{'uu', 'dd'}

對稱差集 XOR

print( A.symmetric_difference(B) )   # All elements in either A or B, but not both
--{'ud', 'du', 'dd', 'uu'}
print( A ^ B )                       # A XOR B
--{'ud', 'du', 'dd', 'uu'}

優(yōu)點缺點

優(yōu)點:不用判斷重復(fù)的元素
缺點:不能存儲可變對象

你看集合的「唯一」特性還不是雙刃劍,既可以是優(yōu)點,又可以是缺點勘天,所有東西都有 trade-off 的,要不然它就沒有存在的必要了捉邢。


3條件語句 & 迭代循環(huán)

在編寫程序時脯丝,我們要

  • 在不同條件下完成不同動作,條件語句 (conditional statement) 賦予程序這種能力伏伐。
  • 重復(fù)的完成某些動作宠进,迭代循環(huán) (iterative loop) 賦予程序這種能力。

3.1條件語句

條件語句太簡單了藐翎,大體有四種格式

  1. if 語句
  2. if-else 語句
  3. if-elif-else 語句
  4. nested 語句

3.1.1 if 語句

給定二元條件材蹬,滿足做事,不滿足不做事吝镣。

if x > 0:
    print( 'x is positive' )

3.1.2 if-else 語句

給定二元條件堤器,滿足做事 A,不滿足做事 B末贾。

if x % 2 == 0:
    print( 'x is even' )
else :
    print( 'x is odd' )

3.1.3 if-elif-else 語句

給定多元條件闸溃,滿足條件 1 做事 A1,滿足條件 2 做事 A2,..., 滿足條件 n 做事 An辉川。直到把所有條件遍歷完掂为。

f x < y:
    print( 'x is less than y' )
elif x > y:
    print( 'x is greater than y' )
else:
    print( 'x and y are equal' )

4. nested 語句

給定多元條件,滿足條件 1 做事 A1员串,不滿足就
滿足條件 2 做事 A2勇哗,不滿足就
...
直到把所有條件遍歷完。

if x == y:
    print( 'x and y are equal' )
else:
    if x < y:
        print( 'x is less than y' )
    else:
        print( 'x is greater than y' )

3.2 迭代循環(huán)

對于迭代循環(huán)寸齐,Python 里面有「while 循環(huán)」和「for 循環(huán)」欲诺,沒有「do-while 循環(huán)」。

3.2.1 while 循環(huán)

n = 5
while n > 0:
    print(n)
    n = n-1
print('I love Python')
5
4
3
2
1
I love Python

While 循環(huán)非常簡單渺鹦,做事直到 while 后面的語句為 False扰法。上例就是打印從 n (初始值為 5) 一直到 1,循環(huán)執(zhí)行了 5 次毅厚。

一般來說塞颁,在 「while 循環(huán)」中,迭代的次數(shù)事先是不知道的吸耿,因為通常你不知道 while 后面的語句從 True 變成 False了祠锣。

3.2.2 for 循環(huán)

更多時候我們希望事先直到循環(huán)的次數(shù),比如在列表咽安、元組伴网、字典等容器類數(shù)據(jù)上遍歷一遍,在每個元素層面上做點事情妆棒。這時候就需要「for 循環(huán)」了澡腾。

languages = ['Python', 'R', 'Matlab', 'C++']
for language in languages:
    print( 'I love', language )
print( 'Done!' )
I love Python
I love R
I love Matlab
I love C++
Done

讀讀 Python 里面的「for 循環(huán)」是不是很像讀英文。通用形式的 for loop 如下

for a in A
    do something with a        

其中 forin 是關(guān)鍵詞糕珊,A 是個可迭代數(shù)據(jù) (list, tuple, dic, set)动分,a 是 A 里面的每個元素.

回到具體例子,for loop 里面的 language 變量在每次循環(huán)中分別取值 Python, R, Matlab 和 C++红选,然后被打印澜公。

最后介紹一個稍微有點特殊的函數(shù) enumerate(),和 for loop 一起用的語法如下

for i, a in enumerate(A)
     do something with a  

發(fā)現(xiàn)區(qū)別了沒纠脾?用 enumerate(A) 不僅返回了 A 中的元素玛瘸,還順便給該元素一個索引值 (默認(rèn)從 0 開始)。此外苟蹈,用 enumerate(A, j) 還可以確定索引起始值為 j糊渊。 看下面例子。

languages = ['Python', 'R', 'Matlab', 'C++']
for i, language in enumerate(languages, 1):
    print( i, 'I love', language )
print( 'Done!' )
1 I love Python
2 I love R
3 I love Matlab
4 I love C++
Done!

4慧脱、函數(shù)

Python 里函數(shù)太重要了 (說的好像在別的語言中函數(shù)不重要似的)渺绒。函數(shù)的通用好處就不用多說了吧,重復(fù)使用代碼,增強代碼可讀性等等宗兼。
還記得 Python 里面『萬物皆對象』么躏鱼?Python 把函數(shù)也當(dāng)成對象,可以從另一個函數(shù)中返回出來而去構(gòu)建高階函數(shù)殷绍,比如

  • 參數(shù)是函數(shù)
  • 返回值是函數(shù)

4.1 正規(guī)函數(shù)

Python 里面的正規(guī)函數(shù) (normal function) 就像其他語言的函數(shù)一樣染苛,之所以說正規(guī)函數(shù)是因為還有些「不正規(guī)」的,比如匿名函數(shù)主到,高階函數(shù)等等茶行。

但即便是正規(guī)函數(shù),Python 的函數(shù)具有非常靈活多樣的參數(shù)形態(tài)登钥,既可以實現(xiàn)簡單的調(diào)用畔师,又可以傳入非常復(fù)雜的參數(shù)。從簡到繁的參數(shù)形態(tài)如下:

位置參數(shù) (positional argument)
默認(rèn)參數(shù) (default argument) 默認(rèn)函數(shù)一定要放在位置參數(shù)后面牧牢,不然程序會報錯看锉。
可變參數(shù) (variable argument)
關(guān)鍵字參數(shù) (keyword argument)
命名關(guān)鍵字參數(shù) (name keyword argument)
參數(shù)組合

每種參數(shù)形態(tài)都有自己對應(yīng)的應(yīng)用,接下來用定義一個金融產(chǎn)品為例來說明各種參數(shù)形態(tài)的具體用法塔鳍。

4.1.1 位置參數(shù)和默認(rèn)參數(shù)

比較簡單伯铣,略過

4.1.2 可變參數(shù)

在 Python 函數(shù)中,還可以定義「可變參數(shù)」献幔。顧名思義懂傀,可變參數(shù)就是傳入的參數(shù)個數(shù)是可變的趾诗,可以是 0, 1, 2 到任意個蜡感。

image.png

金融產(chǎn)品未來多個折現(xiàn)現(xiàn)金流 (discounted cash flow, DCF),但不知道具體多少個恃泪,這時我們可以用 *args 來表示不確定個數(shù)的 DCF郑兴。下面程序也對 DCF 加總得到產(chǎn)品現(xiàn)值 (present value, PV)

def instrument4( id, ntl=1, curR='CNY', *args ):
    PV = 0
    for n in args:
        PV = PV + n

    print( 'id:', id )
    print( 'notional:', ntl )
    print( 'reporting currency:', curR )
    print( 'present value:', PV*ntl )

如果一個產(chǎn)品 (單位本金) 在后 3 年的折現(xiàn)現(xiàn)金流為 1, 2, 3,將它們傳入 args贝乎,計算出它的現(xiàn)值為 600 = 100(1+2+3)情连。

instrument4( 'MM1001', 100, 'EUR', 1, 2, 3 )
--
id: MM1001
notional: 100
reporting currency: EUR
present value: 600

除了直接傳入多個參數(shù)之外,還可以將所有參數(shù)先組裝成元組 DCF览效,用以「*DCF」的形式傳入函數(shù) (DCF 是個元組却舀,前面加個通配符 * 是拆散元組,把元組的元素傳入函數(shù)中)

DCF = (1, 2, 3, 4, 5)
instrument4( 'MM1001', 10, 'EUR', *DCF )
--
id: MM1001
notional: 10
reporting currency: EUR
present value: 150

可變參數(shù)用兩種方式傳入

直接傳入锤灿,func(1, 2, 3)
先組裝列表或元組挽拔,再通過 args 傳入,func([1, 2, 3]) 或 func(*(1, 2, 3))

4.1.3 關(guān)鍵字參數(shù)

image.png

「可變參數(shù)」和「關(guān)鍵字參數(shù)」的同異總結(jié)如下:

  • 可變參數(shù)允許傳入零個到任意個參數(shù)但校,它們在函數(shù)調(diào)用時自動組裝為一個元組 (tuple)
  • 關(guān)鍵字參數(shù)允許傳入零個到任意個參數(shù)螃诅,它們在函數(shù)內(nèi)部自動組裝為一個字典 (dict)

在定義金融產(chǎn)品,有可能不斷增加新的信息,比如交易對手术裸、工作日慣例倘是、工作日計數(shù)慣例等等。我們可以用「關(guān)鍵字參數(shù)」來滿足這種需求袭艺,即用 **kw搀崭。

def instrument5( id, ntl=1, curR='CNY', *args, **kw ):
    PV = 0
    for n in args:
        PV = PV + n

    print( 'id:', id )
    print( 'notional:', ntl )
    print( 'reporting currency:', curR )
    print( 'present value:', PV*ntl )
    print( 'keyword:', kw)

如果不傳入任何「關(guān)鍵字參數(shù)」,kw 為空集猾编。

instrument5( 'MM1001', 100, 'EUR', 1, 2, 3 )
--
id: MM1001
notional: 100
reporting currency: EUR
present value: 600
keyword: {}

當(dāng)知道交易對手 (counterparty) 是高盛時门坷,給函數(shù)傳入一個「關(guān)鍵字參數(shù)」,ctp = 'GS'袍镀。

instrument5( 'MM1001', 100, 'EUR', 1, 2, 3, ctp='GS' )
--
id: MM1001
notional: 100
reporting currency: EUR
present value: 600
keyword: {'ctp': 'GS'}

當(dāng)知道日期計數(shù) (daycount) 是 act/365 時默蚌,再給函數(shù)傳入一個「關(guān)鍵字參數(shù)」,dc = 'act/365'苇羡。

instrument5( 'MM1001', 100, 'EUR', 1, 2, 3, dc='act/365', ctp='GS' )
---
id: MM1001
notional: 100
reporting currency: EUR
present value: 600
keyword: {'dc': 'act/365', 'ctp': 'GS'}

除了直接傳入多個參數(shù)之外绸吸,還可以將所有參數(shù)先組裝成字典 Conv,用以「**Conv」的形式傳入函數(shù) (Conv 是個字典设江,前面加個通配符 ** 是拆散字典锦茁,把字典的鍵值對傳入函數(shù)中)

DCF = (1, 2, 3, 4, 5)
Conv = {'dc':'act/365', 'bdc':'following'}
instrument5( 'MM1001', 10, 'EUR', *DCF, **Conv )
--
id: MM1001
notional: 10
reporting currency: EUR
present value: 150
keyword: {'dc': 'act/365', 'bdc': 'following'}

4.1.4 命名關(guān)鍵字參數(shù)

對于關(guān)鍵字參數(shù),函數(shù)的調(diào)用者可以傳入任意不受限制的關(guān)鍵字參數(shù)叉存。


image.png

如果要限制關(guān)鍵字參數(shù)的名字码俩,就可以用「命名關(guān)鍵字參數(shù)」,例如歼捏,用戶希望交易對手 ctp 是個關(guān)鍵字參數(shù)稿存。這種方式定義的函數(shù)如下:

def instrument6( id, ntl=1, curR='CNY', *, ctp, **kw ):
    print( 'id:', id )
    print( 'notional:', ntl )
    print( 'reporting currency:', curR )
    print( 'counterparty:', ctp )
    print( 'keyword:', kw)

從調(diào)用函數(shù) instrument6 得到的結(jié)果可看出 ctp 是「命名關(guān)鍵字參數(shù)」,而 dc 是「關(guān)鍵字參數(shù)」瞳秽。

instrument6( 'MM1001', 100, 'EUR', dc='act/365', ctp='GS' )
--
id: MM1001
notional: 100
reporting currency: EUR
counterparty: GS
keyword: {'dc': 'act/365'}

使用命名關(guān)鍵字參數(shù)時瓣履,要特別注意不能缺少參數(shù)名。下例沒有寫參數(shù)名 ctp练俐,因此 'GS' 被當(dāng)成「位置參數(shù)」袖迎,而原函數(shù)只有 3 個位置函數(shù),現(xiàn)在調(diào)用了 4 個腺晾,因此程序會報錯:

instrument6( 'MM1001', 100, 'EUR', 'GS', dc='act/365' )
--
TypeError: instrument6() takes from 1 to 3
positional arguments but 4 were given

4.1.5 參數(shù)組合

在 Python 中定義函數(shù)燕锥,可以用位置參數(shù)、默認(rèn)參數(shù)悯蝉、可變參數(shù)归形、命名關(guān)鍵字參數(shù)和關(guān)鍵字參數(shù),這 5 種參數(shù)中的 4 個都可以一起使用泉粉,但是注意连霉,參數(shù)定義的順序必須是:

  • 位置參數(shù)榴芳、默認(rèn)參數(shù)、可變參數(shù)和關(guān)鍵字參數(shù)跺撼。
  • 位置參數(shù)窟感、默認(rèn)參數(shù)、命名關(guān)鍵字參數(shù)和關(guān)鍵字參數(shù)歉井。
    要注意定義可變參數(shù)和關(guān)鍵字參數(shù)的語法:

*args 是可變參數(shù)柿祈,args 接收的是一個 tuple
**kw 是關(guān)鍵字參數(shù),kw 接收的是一個 dict

命名關(guān)鍵字參數(shù)是為了限制調(diào)用者可以傳入的參數(shù)名哩至,同時可以提供默認(rèn)值躏嚎。定義命名關(guān)鍵字參數(shù)不要忘了寫分隔符 *,否則定義的是位置參數(shù)菩貌。

4.2 匿名函數(shù)

在 Python 里有兩種函數(shù):

  • 用 def 關(guān)鍵詞的正規(guī)函數(shù)
  • 用 lambda 關(guān)鍵詞的匿名函數(shù)

匿名函數(shù) (anonymous function) 的說明如下:


image.png
func = lambda x, y: x*y            #函數(shù)輸入是 x 和 y卢佣,輸出是它們的積 x*y
func(2, 3)            --6

func = lambda *args: sum(args)      #輸入是任意個數(shù)的參數(shù),輸出是它們的和
func( 1, 2, 3, 4, 5 )       --15

func = lambda **kwargs: 1             #輸入是任意鍵值對參數(shù)箭阶,輸出是 1
func( name='Steven', age='36' )    --1

正規(guī)函數(shù)vs匿名函數(shù)

lbd_sqr = lambda x: x ** 2
lbd_sqr                  --<function __main__.<lambda>(x)>

def sqr(x):
    return x ** 2
sqr                      --<function __main__.sqr(x)>

print( sqr(9) )          --81
print( lbd_sqr(9) )      --81

4.3高階函數(shù)

高階函數(shù) (high-order function) 在函數(shù)化編程 (functional programming) 很常見虚茶,主要有兩種形式:

  • 參數(shù)是函數(shù) (map, filter, reduce)
  • 返回值是函數(shù) (closure, partial, currying)

4.3.1 Map, Filter, Reduce

Python 里面的 map, filter 和 reduce 屬于第一種高階函數(shù),參數(shù)是函數(shù)仇参。這時候是不是很自然的就想起了 lambda 函數(shù)嘹叫?
作為內(nèi)嵌在別的函數(shù)里的參數(shù),lambda 函數(shù)就像微信小程序一樣诈乒,即用即丟罩扇,非常輕便。

首先看看 map, filter 和 reduce 的語法:

  • map(函數(shù) f, 序列 x):對序列 x 中每個元素依次執(zhí)行函數(shù) f怕磨,將 f(x) 組成一個「map 對象」返回 (可以將其轉(zhuǎn)換成 list 或 set)

  • filter(函數(shù) f, 序列 x):對序列 x 中每個元素依次執(zhí)行函數(shù) f喂饥,將 f(x) 為 True 的結(jié)果組成一個「filter 對象」返回 (可以將其轉(zhuǎn)換成 list 或 set)

  • reduce(函數(shù) f, 序列 x):對序列 x 的第一個和第二個元素執(zhí)行函數(shù) f,得到的結(jié)果和序列 x 的下一個元素執(zhí)行函數(shù) f癌压,一直遍歷完的序列 x 所有元素仰泻。

lst = [1, 2, 3, 4, 5]
map_iter = map( lambda x: x**2, lst )
print( map_iter )                       --<map object at 0x0000018C83E72390>
print( list(map_iter) )                 --[1, 4, 9, 16, 25]

filter_iter = filter(lambda n: n % 2 == 1, lst)
print( filter_iter )                    --<filter object at 0x0000018C83E722E8>
print( list(filter_iter) )              --[1, 3, 5]

from functools import reduce
reduce( lambda x,y: x+y, lst )                 -- 15
reduce( lambda x,y: x+y, lst, 100 )            -- 115

注意 map_iter 是 map 函數(shù)的返回對象 (它是一個迭代器),想要將其內(nèi)容顯示出來滩届,需要用 list 將其轉(zhuǎn)換成「列表」形式。
小結(jié)一下被啼,對于 map, filter 和 reduce帜消,好消息是,Python 支持這些基本的操作浓体;而壞消息是泡挺,Python 不建議你使用它們。下節(jié)的「解析式」可以優(yōu)雅的替代 map 和 filter命浴。

4.3.2 閉包

Python 里面的閉包 (closure) 屬于第二種高階函數(shù)娄猫,返回值是函數(shù)贱除。下面是一個閉包函數(shù)。

def make_counter(init):
    counter = [init]
    
    def inc(): counter[0] += 1
    def dec(): counter[0] -= 1
    def get(): return counter[0]
    def reset(): counter[0] = init
        
    return inc, dec, get, reset

屬于第二類 (返回值是函數(shù)) 的高階函數(shù)還有「偏函數(shù)」和「柯里化」媳溺,由于它們比較特別月幌,因此專門分兩節(jié)來講解。


4.4 偏函數(shù)

偏函數(shù) (paritial function) 主要是把一個函數(shù)的參數(shù) (一個或多個) 固定下來悬蔽,用于專門的應(yīng)用上 (specialized application)扯躺。要用偏函數(shù)用從 functools 中導(dǎo)入 partial 包:

from functools import partial

舉個排序列表里元素的例子

lst = [3, 1, 2, 5, 4]
sorted( lst )                             --[1, 2, 3, 4, 5]

我們知道 sort 函數(shù)默認(rèn)是按升序排列,假設(shè)在你的應(yīng)用中是按降序排列蝎困,你可以把函數(shù)里的 reverse 參數(shù)設(shè)置為 True录语。

sorted( lst, reverse=True )               --[5, 4, 3, 2, 1]

這樣每次設(shè)定參數(shù)很麻煩,你可以專門為「降序排列」的應(yīng)用定義一個函數(shù)禾乘,比如叫 sorted_dec澎埠,用偏函數(shù) partial 把內(nèi)置的 sort 函數(shù)里的 reverse 固定住,代碼如下:

sorted_dec = partial( sorted, reverse=True )
sorted_dec                          --functools.partial(<built-in function sorted>, reverse=True)

不難發(fā)現(xiàn) sorted_dec 是一個函數(shù)始藕,而且參數(shù)設(shè)置符合我們的應(yīng)用失暂,把該函數(shù)用到列表就能對于降序排列。

sorted_dec( lst )                            --[5, 4, 3, 2, 1]

小結(jié)鳄虱,當(dāng)函數(shù)的參數(shù)個數(shù)太多弟塞,需要簡化時,使用 functools.partial 可以創(chuàng)建一個新的函數(shù)拙已,即偏函數(shù)决记,它可以固定住原函數(shù)的部分參數(shù),從而在調(diào)用時更簡單倍踪。

4.5 柯里化

最簡單的柯里化 (currying) 指的是將原來接收 2 個參數(shù)的函數(shù) f(x, y) 變成新的接收 1 個參數(shù)的函數(shù) g(x) 的過程系宫,其中新函數(shù) g = f(y)。

以普通的加法函數(shù)為例:

#參數(shù)是 x 和 y建车,輸出 x + y
def add1(x, y):              
    return x + y

# 通過嵌套函數(shù)可以把函數(shù) add1 轉(zhuǎn)換成柯里化函數(shù) add2扩借。
# 參數(shù)是 x,輸出 x + y
def add2(x):                    
    def add(y):
        return x + y
    return add

#參數(shù)是 y缤至,輸出 2 + y
g = add2(2)           


print( add1(2, 3) )                --5
print( add2(2)(3) )                --5
print( g(3) )                      --5

比較「普通函數(shù) add1」和「柯里化函數(shù) add2」的調(diào)用潮罪,結(jié)果都一樣。


5 解析式

解析式 (comprehension) 是將一個可迭代對象轉(zhuǎn)換成另一個可迭代對象的工具领斥。
第一個可迭代對象:可以是任何容器類型數(shù)據(jù)嫉到。
第二個可迭代對象:

  • 列表解析式:可迭代對象是 list
  • 字典解析式:可迭代對象是 dict
  • 集合解析式:可迭代對象是 set

5.1 列表解析式

#從一個含整數(shù)列表中把奇數(shù) (odd number) 挑出來
lst = [1, 2, 3, 4, 5] 
odds = []
for n in lst:
    if n % 2 == 1:
        odds.append(n )
odds                                     --[1, 3, 5]

#任務(wù)完成了,但這個代碼有好幾行呢月洛,不簡潔何恶,看看下面這一行代碼:
odds = [n  for n in lst if n % 2 == 1]
odds                                     --[1, 3, 5]

你可以把「for 循環(huán)」到「解析式」的過程想像成一個「復(fù)制-粘貼」的過程:

  • 將「for 循環(huán)」的新列表復(fù)制到「解析式」里
  • 將 append 里面的表達(dá)式 n 復(fù)制到新列表里
  • 復(fù)制循環(huán)語句 for n in lst 到新列表里,不要最后的冒號
  • 復(fù)制條件語句 if n%2 == 1 到新列表里嚼黔,不要最后的冒號


    image.png
#用「列表解析式」將一個二維列表中的元素按行一個個展平
# for循環(huán)
flattened = []
for row in lst:
    for n in row:
        flattened.append(n)
# 解析式:
flattened = [n for row in lst for n in row]

再回顧下三種解析式细层,我們發(fā)現(xiàn)其實它們都可以實現(xiàn)上節(jié)提到的 filter 和 map 函數(shù)的功能惜辑,用專業(yè)計算機的語言說,解析式可以看成是 filter 和 map 函數(shù)的語法糖疫赎。


image.png
# 列表解析式
[ n*2 for n in lst if n%2 == 1]
# map/filter
list( map(lambda n: n*2, filter(lambda n: n%2 == 1, lst)) )

5.2 例子

# 用解析式將二維元組里每個元素提取出來并存儲到一個列表中盛撑。
tup = ((1, 2, 3), (4, 5, 6), (7, 8, 9))
flattened = [x for t in tup for x in t]
flattened                             --[1, 2, 3, 4, 5, 6, 7, 8, 9]

#把上面「二維元組」轉(zhuǎn)換成「二維列表」
[ [x for x in t] for t in tup ]       --[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

# 用解析式把以下這個不規(guī)則的列表 a 打平 (flatten)
# 正規(guī)函數(shù)
a = [1, 2, [3, 4], [[5, 6], [7, 8]]]
def f(x):
    if type(x) is list:
        return [y for l in x for y in f(l)]
    else:
        return [x]

f(a)                                  --[1, 2, 3, 4, 5, 6, 7, 8]

a = [1, 2, [3, 4], [[5, 6], [7, 8]]]
f = lambda x: [y for l in x for y in f(l)] 
               if type(y) is list else [x]
f(a)                                 --[1, 2, 3, 4, 5, 6, 7, 8]

函數(shù) f(x) 是一個遞推函數(shù),當(dāng) x 是元素虚缎,返回 [x], 那么
f(1) 的返回值是 [1]
f(2) 的返回值是 [2]
當(dāng) x 是列表撵彻,返回 [y for l in x for y in f(l)],當(dāng) x = [3 ,4] 時
for l in x:指的是 x 里每個元素 l实牡,那么 l 遍歷 3 和 4
for y in f(l):指的是 f(l) 里每個元素 y
當(dāng) l = 3陌僵,是個元素,那么 f(l) = [3], y 遍歷 3
當(dāng) l = 4创坞,是個元素碗短,那么 f(l) = [4], y 遍歷 4


總結(jié)

數(shù)據(jù)類型分兩種:
單獨類型:整型、浮點型题涨、布爾型
容器類型:字符偎谁、元組、列表纲堵、字典巡雨、集合

條件語句 (if, if-else, if-elif-else, nested if) 是為了在不同條件下執(zhí)行不同操作,而迭代循環(huán) (while, for) 是重復(fù)的完成相同操作席函。

函數(shù)包括正規(guī)函數(shù) (用 def) 和匿名函數(shù) (用 lambda)铐望,函數(shù)的參數(shù)形態(tài)也多種多樣,有位置參數(shù)茂附、默認(rèn)參數(shù)正蛙、可變參數(shù)、關(guān)鍵字參數(shù)营曼、命名關(guān)鍵字參數(shù)乒验。匿名函數(shù)主要用在高階函數(shù)中,高階函數(shù)的參數(shù)可以是函數(shù) (Python 里面內(nèi)置 map/filter/reduce 函數(shù))蒂阱,返回值也可以是參數(shù) (閉包锻全、偏函數(shù)、柯里化函數(shù))蒜危。

解析式并沒有解決新的問題虱痕,只是以一種更加簡潔,可讀性更高的方式解決老的問題辐赞。解析式可以把「帶 if 條件的 for 循環(huán)」用一行程序表達(dá)出來,也可以實現(xiàn) map 加 filter 的功能硝训。

按照 Python 里「萬物皆對象」的思路响委,學(xué)習(xí)每一個對象里面的屬性 (attributes) 和方法 (methods)新思,你不需要記住所有,有個大概印象有哪些赘风,通過 dir() 來鎖定具體表達(dá)式夹囚,再去官網(wǎng)上查詢所有細(xì)節(jié)。這么學(xué)真的很系統(tǒng)而簡單邀窃。此外學(xué)的時候一定要帶著“它的優(yōu)缺點是什么”這樣的問題荸哟,所有東西都有 trade-off,一個滿身都是缺點的東西就沒有存在的必要瞬捕,既然存在肯定有可取之處鞍历。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市肪虎,隨后出現(xiàn)的幾起案子劣砍,更是在濱河造成了極大的恐慌,老刑警劉巖扇救,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刑枝,死亡現(xiàn)場離奇詭異,居然都是意外死亡迅腔,警方通過查閱死者的電腦和手機装畅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沧烈,“玉大人掠兄,你說我怎么就攤上這事〔舫觯” “怎么了徽千?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長汤锨。 經(jīng)常有香客問我双抽,道長,這世上最難降的妖魔是什么闲礼? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任牍汹,我火速辦了婚禮,結(jié)果婚禮上柬泽,老公的妹妹穿的比我還像新娘慎菲。我一直安慰自己,他們只是感情好锨并,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布露该。 她就那樣靜靜地躺著,像睡著了一般第煮。 火紅的嫁衣襯著肌膚如雪解幼。 梳的紋絲不亂的頭發(fā)上抑党,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天,我揣著相機與錄音撵摆,去河邊找鬼底靠。 笑死,一個胖子當(dāng)著我的面吹牛特铝,可吹牛的內(nèi)容都是我干的暑中。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼鲫剿,長吁一口氣:“原來是場噩夢啊……” “哼鳄逾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起牵素,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤严衬,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后笆呆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體请琳,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年赠幕,在試婚紗的時候發(fā)現(xiàn)自己被綠了俄精。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡榕堰,死狀恐怖竖慧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情逆屡,我是刑警寧澤圾旨,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站魏蔗,受9級特大地震影響砍的,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜莺治,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一廓鞠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧谣旁,春花似錦床佳、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春怨绣,著一層夾襖步出監(jiān)牢的瞬間角溃,已是汗流浹背拷获。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工篮撑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人匆瓜。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓赢笨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親驮吱。 傳聞我的和親對象是個殘疾皇子茧妒,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 一、Python簡介和環(huán)境搭建以及pip的安裝 4課時實驗課主要內(nèi)容 【Python簡介】: Python 是一個...
    _小老虎_閱讀 5,723評論 0 10
  • Python標(biāo)識符 在 Python 里左冬,標(biāo)識符有字母桐筏、數(shù)字、下劃線組成拇砰。在 Python 中梅忌,所有標(biāo)識符可以包括...
    tianyi6677閱讀 1,080評論 0 3
  • 1.基本使用 1.1 數(shù)據(jù)類型 常用數(shù)據(jù)類型 Common Data Types 其他類型 Others 1.2 ...
    suwi閱讀 1,330評論 0 3
  • 周末沒有看自虐組指定的書籍,讀了寂靜法師寫的《讓孩子成才的秘密》除破,讀到最后發(fā)現(xiàn)一個問題是——孩子成才與否牧氮,跟孩子沒...
    定平sunny閱讀 230評論 0 0
  • 除我之外 都是外面 在里面 我與我 每日每日矛盾又簡單的生活著 一個人 也很精彩 走出去 看向外面 人與人 車與車...
    守夜日記閱讀 106評論 0 2