Python提供的一些相當實用而靈活的通用數據結構

程序員書屋 發佈 2020-04-15T11:24:06+00:00

In[130]: for value in d.values(): print) <class 'int'>本文截選自《Python金融大數據分析》第2版本書總計分為5部分,共21章。

拙劣的程式設計師擔心代碼。好的程式設計師擔心數據結構及它們的關係。

——林納斯•托瓦茲

本章介紹Python的基本數據類型和數據結構,它們按照如下方式組織。

基本數據類型

3.1節介紹整數、浮點數和字符串等基本數據類型。

基本數據結構

3.2節介紹Python的基本數據結構(例如List對象)並闡述控制結構、函數式編程范型以及匿名函數。

本章的主旨是提供Python數據類型和結構細節的一般介紹。如果您有其他程式語言(如C或者Matlab)的背景,應該能夠輕鬆地掌握Python使用方法帶來的差異。本章介紹的主題是後續章節的重要基礎,涵蓋了以下數據類型與結構。

3.1 基本數據類型

Python是一種動態類型的語言,這意味著,Python解釋程序在運行時推斷對象的類型。C等編譯語言通常是靜態類型語言,在這類語言中,對象類型必須在編譯之前與對象綁定[1]。

3.1.1 整數

最基本的數據類型是整數int:

In [1]: a = 10
        type(a)
Out[1]: int

內建函數type為所有使用標準和內建類型的對象、新創建的類及對象提供類型信息。在後一種情況下,提供的信息取決於程式設計師存儲在類中的描述。有一種說法:「在Python中,一切都是對象。」這意味著,即使我們剛剛定義的簡單對象int也有內建方法。例如,您可以調用bit_length方法,獲得表現整數對象所需的位數:

In [2]: a.bit_length()
Out[2]: 4

您將會看到,我們為該對象所賦的整數值越大,需要的位數就越多:

In [3]: a = 100000
        a.bit_length()
Out[3]: 17

一般來說,這類方法很多,很難記住所有類和對象的所有方法。高級Python環境(如IPython)提供Tab鍵完成功能,以顯示對象連接的所有方法。您只需要輸入對象名和一個點(如a.)然後按下Tab鍵,就會提供一組可以在該對象上調用的方法。也可以使用Python內建函數dir顯示任何對象屬性和方法的完整列表。

Python的特殊性之一是整數可以任意大。例如,考慮天文數字10100。Python處理這樣大的數毫無問題,這從技術上說是一個很「長」的對象:

In [4]: googol = 10 ** 100
        googol
Out[4]:  1000000000000000000000000000000000000000000000000000000000000
        000000000000000000000000000000000000000
In [5]: googol.bit_length()
Out[5]: 333

 

大整數

Python整數可以為任意大。解釋程序簡單地使用所需的位/字節數就可表現數值。

整數的算術運算也很容易實現:

In [6]: 1 + 4
Out[6]: 5

In [7]: 1 / 4
Out[7]: 0.25

In [8]: type(1 / 4)
Out[8]: float

3.1.2 浮點數

為了讓上一個表達式返回所需的值——0.25[2],我們必須在浮點(float)對象上操作,這很自然地把我們帶到下一種基本數據類型。在整數值上加一個點比如1.或者1.0,會導致Python將該對象解釋為浮點數。涉及浮點數的表達式通常也必須返回一個浮點對象[3]:

In [9]: 1.6 / 4
Out[9]: 0.4
In [10]: type (1.6 / 4)
Out[10]: float

浮點數與通常不精確的實數計算機表現形式關係更大,取決於所採用的具體技術方法。為了說明其中的含義,我們定義另一個浮點對象b,這種浮點對象在內部總是只表現為某種精度。將b加上0.1時,這一點變得很明顯:

In [11]: b = 0.35
         type(b)
Out[11]: float

In [12]: b + 0.1
Out[12]: 0.44999999999999996

出現以上結果的原因是浮點數在計算機內部以二進位形式表示;也就是說,十進位數n(0<n<1)表現為如下形式:

對於某些浮點數,二進位表現形式可能包含大量元素甚至是一個無限系列。但是,考慮到用於表達這種數值的位數是固定的——也就是表現系列中的項目固定,因此結果是不精確的。其他數值可以完整表現,因此在可用位數有限時也可以精確地被存儲。考慮如下例子:

In [13]: c = 0.5
         c.as_integer_ratio()
Out[13]: (1, 2)

0.5可以精確保存,因為它具備精確(有限)的二進位表示:0.5=1/2。但是,b=0.35和預期的實數0.35=7/20不同:

In [14]: b.as_integer_ratio()
Out[14]: (3152519739159347, 9007199254740992)

精度取決於表示數值所用的位數。一般來說,Python運行的所有平台使用IEEE 754雙精度標準(64位)作為內部表示,這相當於15位數字的相對精度。

由於這個主題在金融應用領域中很重要,所以有時候必須確保數值的精確(至少儘可能達到最佳)。例如,在加總一組數量很多的數值時,這個問題就可能很重要。在這種情況下,某個種類或者幅度的表示誤差可能匯聚起來,從而造成和基準值的顯著偏差。

decimal模塊為浮點數提供了任意精確度的對象,以及使用這些數值時處理精度問題的多個選項:

In [15]: import decimal
         from decimal import Decimal

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

In [17]: d = Decimal(1) / Decimal (11)
d
Out[17]: Decimal('0.09090909090909090909090909091')

您可以改變Context對象的各個屬性值,從而改變表示的精度:

In [18]: decimal.getcontext().prec = 4❶

In [19]: e = Decimal(1) / Decimal (11)
         e
Out[19]: Decimal('0.09091')

In [20]: decimal.getcontext().prec = 50❷

In [21]: f = Decimal(1) / Decimal (11)
         f
Out[21]: Decimal('0.090909090909090909090909090909090909090909090909091')

❶ 精度低於默認值。

❷ 精度高於默認值。

如果有必要,精度可以這樣按照具體的問題進行調整,人們可以使用不同精度的浮點對象進行運算:

In [22]: g = d + e + f
         g
Out[22]: Decimal('0.27272818181818181818181818181909090909090909090909')

 

任意精度浮點數

decimal模塊可提供任意精度浮點數對象。在金融領域中,確保高精度、超出64位雙精度標準有時是必要的。

3.1.3 布爾值

在編程中,比較或者邏輯表達式(如4 > 3, 4.5 <= 3.25 或 (4 > 3) and (3 > 2))得到的輸出為True或者False,這是兩個重要的Python關鍵字。其他重要的關鍵字有def、for和if等。Python的關鍵字列表可以在keyword模塊中找到:

In [23]: import keyword

In [24]: keyword.kwlist
Out[24]: ['False',
          'None',
          'True',
          'and',
          'as',
          'assert',
          'async',
          'await',
          'break',
          'class',
          'continue',
          'def',
          'del',
          'elif',
          'else',
          'except',
          'finally',
          'for',
          'from',
          'global',
          'if',
          'import',
          'in',
          'is',
          'lambda',
          'nonlocal',
          'not',
          'or',
          'pass',
          'raise',
          'return',
          'try',
          'while',
          'with',
          'yield']

True和Flase的數據類型為bool,表示「布爾值」(Boolean Value)。將Python的比較運算符應用到相同操作數時結果為布爾對象:

In [25]: 4 > 3❶
Out[25]: True

In [26]: type(4 > 3)
Out[26]: bool

In [27]: type(False)
Out[27]: bool

In [28]: 4 >= 3❷
Out[28]: True

In [29]: 4 < 3❸
Out[29]: False

In [30]: 4 <= 3❹
Out[30]: False

In [31]: 4 == 3❺
Out[31]: False

In [32]: 4 != 3❻
Out[32]: True

❶ 大於。

❷ 大於或等於。

❸ 小於。

❹ 小於或等於。

❺ 等於。

❻ 不等於。

邏輯運算往往應用到布爾對象上,然後得出另一個布爾對象:

In [33]: True and True
Out[33]: True

In [34]: True and False
Out[34]: False

In [35]: False and False
Out[35]: False

In [36]: True or True
Out[36]: True

In [37]: True or False
Out[37]: True

In [38]: False or False
Out[38]: False

In [39]: not True
Out[39]: False

In [40]: not False
Out[40]: True

當然,兩類運算符往往組合使用:

In [41]: (4 > 3) and (2 > 3)
Out[41]: False

In [42]: (4 == 3) or (2 != 3)
Out[42]: True

In [43]: not (4 != 4)
Out[43]: True

In [44]: (not (4 != 4)) and (2 == 3)
Out[44]: False

布爾值的重要應用領域之一是通過其他Python關鍵字(如if或while,本章後面將有更多示例)控制代碼流程:

In [45]: if 4 > 3: ❶
              print('condition true') ❷
         condition true
In [46]: i = 0 ❸
         while i < 4: ❹
             print('condition true, i = ', i) ❺
             i += 1 ❻
         condition true, i = 0
         condition true, i = 1
         condition true, i = 2
         condition true, i = 3

❶ 如果條件為真,執行以下代碼。

❷ 如果條件為真,執行這段代碼。

❸ 將參數i初始化為0。

❹ 只要條件為0,就執行並重複以下代碼。

❺ 列印文本和參數i的值。

❻ 將參數增加1;i += 1與i = i + 1等價。

從數值上講,Python為False賦值0,為True賦值1。當通過bool()函數將數值轉換成bool對象時,0值轉換成False,其他所有值都轉換為True:

In [47]: int(True)
Out[47]: 1

In [48]: int(False)
Out[48]: 0

In [49]: float(True)
Out[49]: 1.0

In [50]: float(False)
Out[50]: 0.0

In [51]: bool(0)
Out[51]: False

In [52]: bool(0.0)
Out[52]: False

In [53]: bool(1)
Out[53]: True

In [54]: bool(10.5)
Out[54]: True

In [55]: bool(-2)
Out[55]: True

3.1.4 字符串

既然我們已經可以表示自然和浮點數,現在就可以轉向文本了。Python中表示文本的基本數據類型是字符串——str,字符串對象有一些真正實用的內建方法。實際上,Python通常被視為處理任何類型、任何尺寸文本文件的很好選擇。字符串對象通常由單引號或者雙引號定義或者使用str()函數轉換而來(也就是使用對象的標準或者用戶定義的字符串表示):

In [56]: t = 'this is a string object'

舉個內建方法的例子,您可以將對象中的第一個詞改為首字母大寫:

In [57]: t.capitalize()
Out[57]: 'This is a string object'

也可以將字符串拆分成單個詞,以獲得包含所有單詞的列表對象:

In [58]: t.split()
Out[58]: ['this', 'is', 'a', 'string', 'object']

您還可以搜索一個單詞,如果搜索成功,就可以得到該詞第一個字母的位置(即索引值):

In [59]: t.find('string')
Out[59]: 10

如果這個單詞不在字符串對象中,該方法返回-1:

In [60]: t.find('Python')
Out[60]: -1

替換字符串中的字符是典型的任務,可以用replace()方法簡單地完成:

In [61]: t.replace(' ', '|')
Out[61]: 'this|is|a|string|object'

字符串「剝離」(stripping)操作——刪除某些前導或者後綴字符也是必要的:

In [62]: 'http://www.python.org'.strip('htp:/')
Out[62]: 'www.python.org'

表3-1列出了字符串對象的一些實用方法。


Unicode字符串

Python 2.7(本書第1版使用)到Python 3.7(本書第2版使用)的根本變化之一是字符串對象的編碼與解碼方法,以及Unicode的引入。本章不介紹這方面的細節;本書主要處理數值數據和包含英語單詞的標準字符串,這種忽略似乎是合理的。

3.1.5 題外話:列印和字符串替換

列印字符串對象或者其他Python對象的字符串表示,通常由print()函數完成:

In [63]: print('Python for Finance') ❶
         Python for Finance

In [64]: print(t) ❷
         this is a string object

In [65]: i = 0
         while i < 4:
             print(i) ❸
             i += 1
         0
         1
         2
         3
In [66]: i = 0
         while i < 4:
             print(i, end='|') ❹
             i += 1
         0|1|2|3|

❶ 列印一個str對象。

❷ 列印變量名引用的字符串對象。

❸ 列印整數對象的字符串表示。

❹ 指定列印的結束符,默認為前面見到的換行符(\n)

Python提供了強大的字符串替換運算。我們可以採用舊方法通過%字符,也可以採用通過花括號({})和format()函數的新方法。兩種方法在實踐中都適用。本節無法提供所有選項的說明,但以下代碼片段可以展示一些重要的選項。首先是舊方法:

In [67]: 'this is an integer %d' % 15 ❶
Out[67]: 'this is an integer 15'

In [68]: 'this is an integer %4d' % 15 ❷
Out[68]: 'this is an integer 15'

In [69]: 'this is an integer %04d' % 15 ❸
Out[69]: 'this is an integer 0015'

In [70]: 'this is a float %f' % 15.3456 ❹
Out[70]: 'this is a float 15.345600'

In [71]: 'this is a float %.2f' % 15.3456 ❺
Out[71]: 'this is a float 15.35'

In [72]: 'this is a float %8f' % 15.3456 ❻
Out[72]: 'this is a float 15.345600'

In [73]: 'this is a float %8.2f' % 15.3456 ❼
Out[73]: 'this is a float 15.35'

In [74]: 'this is a float %08.2f' % 15.3456 ❽
Out[74]: 'this is a float 00015.35'

In [75]: 'this is a string %s' % 'Python' ❾
Out[75]: 'this is a string Python'

In [76]: 'this is a string %10s' % 'Python' ❿
Out[76]: 'this is a string Python'

❶ 整數對象替換。

❷ 固定數量的字符

❸ 必要時加上前導0。

❹ 浮點數對象替換。

❺ 固定小數位數。

❻ 固定數量字符(以及填充的小數位數)。

❼ 固定數量字符和小數位數…

❽ 必要時加上前導0。

❾ 字符串對象替換。

❿ 固定字符數。

下面是同樣的例子,但用新方法實現。注意某些位置輸出的細微差別:

In [77]: 'this is an integer {:d}'.format(15)
Out[77]: 'this is an integer 15'

In [78]: 'this is an integer {:4d}'.format(15)
Out[78]: 'this is an integer 15'

In [79]: 'this is an integer {:04d}'.format(15)
Out[79]: 'this is an integer 0015'

In [80]: 'this is a float {:f}'.format(15.3456)
Out[80]: 'this is a float 15.345600'

In [81]: 'this is a float {:.2f}'.format(15.3456)
Out[81]: 'this is a float 15.35'

In [82]: 'this is a float {:8f}'.format(15.3456)
Out[82]: 'this is a float 15.345600'

In [83]: 'this is a float {:8.2f}'.format(15.3456)
Out[83]: 'this is a float 15.35'

In [84]: 'this is a float {:08.2f}'.format(15.3456)
Out[84]: 'this is a float 00015.35'

In [85]: 'this is a string {:s}'.format('Python')
Out[85]: 'this is a string Python'

In [86]: 'this is a string {:10s}'.format('Python')
Out[86]: 'this is a string Python '

字符串替換在多次列印更新的數據時特別有用,例如在while循環中:

In [87]: i = 0
         while i < 4:
             print('the number is %d' % i)
             i += 1
         the number is 0
         the number is 1
         the number is 2
         the number is 3
In [88]: i = 0
         while i < 4:
             print('the number is {:d}'.format(i))
             i += 1
         the number is 0
         the number is 1
         the number is 2
         the number is 3

3.1.6 題外話:正則表達式

正則表達式是處理字符串對象的一個強大工具。Python在re模塊中提供了這個功能:

In [89]: import re

假定您現在面對一個大的文本文件,例如逗號分隔值(CSV)文件,其中包含了某些事件序列和相應的日期-時間信息。日期-時間信息多半以Python無法直接解釋的格式提供。然而,日期-時間信息通常可以通過正則表達式描述。考慮如下的字符串對象,它包含3個日期-時間元素、3個整數和3個字符串。注意,3個引號可以定義多行字符串:

In [90]: series = """
         '01/18/2014 13:00:00', 100, '1st';
         '01/18/2014 13:30:00', 110, '2nd';
         '01/18/2014 14:00:00', 120, '3rd'
         """

下面的正則表達式描述了上述字符串對象提供的日期-時間信息格式[4]:

In [91]: dt = re.compile("'[0-9/:\s]+'") # datetime

使用上述正則表達式,我們可以查找所有日期-時間元素。一般來說,對字符串對象應用正則表達式還能帶來典型解析任務性能的提升。

In [92]: result = dt.findall(series)
         result
Out[92]: ["'01/18/2014 13:00:00'", "'01/18/2014 13:30:00'", "'01/18/2014
         14:00:00'"]

 

正則表達式

解析字符串對象時,若考慮使用正則表達式,可以為相關操作帶來便利和高性能。

然後,可以對結果字符串對象進行解析,生成Python的日期時間(datetime)對象(用Python處理日期和時間數據的概述參見附錄A)。要解析包含日期時間信息的字符串對象,我們必須提供解析方法的信息——同樣是一個字符串對象:

In [93]: from datetime import datetime
         pydt = datetime.strptime(result[0].replace("'", ""),
                                  '%m/%d/%Y %H:%M:%S')
         pydt
Out[93]: datetime.datetime(2014, 1, 18, 13, 0)

In [94]: print(pydt)
         2014-01-18 13:00:00

In [95]: print(type(pydt))
         <class 'datetime.datetime'>

後續內容會提供關於日期—時間數據、這些數據的處理以及datetime對象及其方法的更多信息。現在我們只是預覽一下金融中的這個重要主題。

3.2 基本數據結構

數據結構是包含其他對象(可能很多)的對象。Python提供了以下內建結構。

元組(tuple)

任意對象的集合;只有少數可用方法。

列表(list)

任意對象的集合;有許多可用方法。

字典(dict)

鍵-值存儲對象。

集合(set)

其他獨特對象的無序集合對象。

3.2.1 元組

元組(tuple)是一種高級的數據結構,其應用相當簡單有限。它通過圓括號來提供對象定義:

In [96]: t = (1, 2.5, 'data')
         type(t)
Out[96]: tuple

也可以去掉括號,提供以逗號分隔的多個對象:

In [97]: t = 1, 2.5, 'data'
         type(t)
Out[97]: tuple

和Python中幾乎所有的數據結構相似,元組有內建的索引,利用該索引可以讀取元組的單個或者多個元素。重要的是記住Python使用零起點編號,元組的第3個元素在索引位置2上:

In [98]: t[2]
Out[98]: 'data'

In [99]: type(t[2])
Out[99]: str

 

零起點編號

與MATLAB等其他程式語言不同,Python使用零起點編號方案。例如,元組對象的第一個元素索引值為0。

這種對象類型只有兩個特殊方法:count()和index()。第一個方法計算某個對象的出現次數,第二個方法給出對象第一次出現位置的索引值:

In [100]: t.count('data')
Out[100]: 1

In [101]: t.index(1)
Out[101]: 0

元組對象是不可變對象,這意味著一旦定義,它們就不容易更改。

3.2.2 列表

與元組對象相比,列表(list)類型的對象更靈活、更強大。從金融角度看,許多工作只能用列表對象完成,例如存儲股票報價和附加新數據。列表對象通過方括號定義,其基本功能和行為與元組類似:

In [102]: l = [1, 2.5, 'data']
          l[2]
Out[102]: 'data'

列表對象也可以使用list()函數定義或者轉換。下面的代碼通過轉換前一個例子中的元組對象來生成新的列表對象:

In [103]: l = list(t)
          l
Out[103]: [1, 2.5, 'data']

In [104]: type(l)
Out[104]: list

除了元組對象的特性之外,列表對象還可以通過不同的方法來擴展和縮小。換句話說,字符串和元組對象是不可變序列對象(具有索引),一經創建不能更改,而列表對象是可變的,可以通過不同操作更改。您可以在現有列表對象中附加一個或者多個列表對象:

In [105]: l.append([4, 3]) ❶
          l
Out[105]: [1, 2.5, 'data', [4, 3]]

In [106]: l.extend([1.0, 1.5, 2.0]) ❷
          l
Out[106]: [1, 2.5, 'data', [4, 3], 1.0, 1.5, 2.0]

In [107]: l.insert(1, 'insert') ❸
          l
Out[107]: [1, 'insert', 2.5, 'data', [4, 3], 1.0, 1.5, 2.0]
In [108]: l.remove('data') ❹
          l
Out[108]: [1, 'insert', 2.5, [4, 3], 1.0, 1.5, 2.0]

In [109]: p = l.pop(3) ❺
          print(l, p)
          [1, 'insert', 2.5, 1.0, 1.5, 2.0] [4, 3]

❶ 在尾部附加列表對象。

❷ 附加列表對象元素。

❸ 在索引位置之前插入對象。

❹ 刪除第一次出現的對象。

❺ 刪除並返回索引位置的對象。

切片操作也很容易實現。這裡的切片(slicing)指的是將數據集分解為(感興趣的)較小部分:

In [110]: l[2:5] ❶
Out[110]: [2.5, 1.0, 1.5]

❶ 返回的是第3~5個元素。

表3-2提供了列表對象精選操作和方法的簡單說明。


3.2.3 題外話:控制結構

控制結構(如for循環)本身就是一個主題,但是在Python中,最好在列表對象基礎上理解它。這是因為:循環一般來說都在列表對象上進行,這與其他語言中的常用標準有很大不同。看下面的例子,for循環在列表對象l索引值為2~4的元素上進行,功能是列印各個元素的平方。注意第二行中縮進(空白)的重要性:

In [111]: for element in l[2:5]:
              print(element ** 2)
          6.25
          1.0
          2.25

與典型的基於計數器的循環相比,上述循環提供了很高的靈活性。基於計數器的循環也是Python的一個可選項,但是在(標準)列表對象range的基礎上完成的:

In [112]: r = range(0, 8, 1) ❶
          r
Out[112]: range(0, 8)

In [113]: type(r)
Out[113]: range

❶ 參數依次是起始值、結束值和步長。

為了比較,下面我們使用range實現同一個循環:

In [114]: for i in range(2, 5):
              print(l[i] ** 2)
          6.25
          1.0
          2.25

 

在列表上循環

在Python中,你可以在任意列表對象上循環,而不用管這些對象的內容是什麼,這往往可以避免引入計數器。

Python還提供了典型(條件)控制元素if、elif和else。它們的用途與其他語言的相同:

In [115]: for i in range(1, 10):
              if i % 2 == 0: ❶
                  print("%d is even" % i)
              elif i % 3 == 0:
                  print("%d is multiple of 3" % i)
              else:
                  print("%d is odd" % i)
          1 is odd
          2 is even
          3 is multiple of 3
          4 is even
          5 is odd
          6 is even
          7 is odd
          8 is even
          9 is multiple of 3
          % stands for modulo.

❶ %代表取模運算。

同樣,while提供了另一種流程控制手段:

In [116]: total = 0
          while total < 100:
              total += 1
          print(total)
          100

Python的特殊性之一是所謂的列表推導(List Comprehension)。這種方法不在現有列表對象上循環,而是以緊湊的方式通過循環生成列表對象:

In [117]: m = [i ** 2 for i in range(5)]
          m
Out[117]: [0, 1, 4, 9, 16]

在某種意義上,它已經提供了一種方法,以較為隱含(而非顯式)的循環生成某種向量化代碼段(代碼向量化將在第4章和第5章中詳細討論)。

3.2.4 題外話:函數式編程

Python也提供一些用於函數式編程支持的工具——在一整組輸入(在我們的例子中是列表對象)上應用某個函數。這些工具是過濾(filter)、映射(map)和歸納(reduce)。但是,我們首先需要一個函數定義。從簡單的功能出發,考慮以下的函數f,它返回輸入x的平方數:

In [118]: def f(x):
              return x ** 2
          f(2)
Out[118]: 4

當然,函數可能很複雜,它可能有多個輸入(參數對象)甚至多個輸出(返回對象)。考慮以下函數:

In [119]: def even(x):
              return x % 2 == 0
          even(3)
Out[119]: False

返回對象是一個布爾值。這樣的函數可以用map()應用到整個列表對象:

In [120]: list(map(even, range(10)))
Out[120]: [True, False, True, False, True, False, True, False, True, False]

為此,我們還可以使用lambda或者匿名函數,直接提供一個函數定義作為map()的參數:

In [121]: list(map(lambda x: x ** 2, range(10)))
Out[121]: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

函數也可以用於過濾列表對象。在下面的例子中,過濾器返回列表對象中匹配某個布爾條件(由even函數定義)的元素:

In [122]: list(filter(even, range(15)))
Out[122]: [0, 2, 4, 6, 8, 10, 12, 14]

 

列表推導、函數式編程和匿名函數

在Python級別上儘可能避免循環被視為「好的習慣」。列表推導和函數式編程工具(如map、filter和reduce)為編寫緊湊(一般來說也更易於理解)無循環代碼提供了很大幫助。lambda或者匿名函數也是這方面的強大工具。

3.2.5 字典

字典(dict)對象就是可以按照鍵碼(例如,可能是字符串對象)讀取的數據字典,也是一種可變序列,是所謂的鍵—值存儲。列表對象是有序且可排序的,而字典對象通常是無序、不可排序的[5]。示例最能夠說明字典和列表對象的不同之處。字典對象定義用花括號實現:

In [123]: d = {
               'Name' : 'Angela Merkel',
               'Country' : 'Germany',
               'Profession' : 'Chancelor',
               'Age' : 64
               }
          type(d)
Out[123]: dict

In [124]: print(d['Name'], d['Age'])
          Angela Merkel 64

同樣,該類對象也有一些內建方法:

In [125]: d.keys()
Out[125]: dict_keys(['Name', 'Country', 'Profession', 'Age'])

In [126]: d.values()
Out[126]: dict_values(['Angela Merkel', 'Germany', 'Chancelor', 64])

In [127]: d.items()
Out[127]: dict_items([('Name', 'Angela Merkel'), ('Country', 'Germany'),
          ('Profession', 'Chancelor'), ('Age', 64)])

In [128]: birthday = True
          if birthday:a
              d['Age'] += 1
          print(d['Age'])
          65

從字典對象中獲得疊代器(Iterator)對象有多種方法。這種對象在循環時的表現與列表對象的表現類似:

In [129]: for item in d.items():
              print(item)
          ('Name', 'Angela Merkel')
          ('Country', 'Germany')
          ('Profession', 'Chancelor')
          ('Age', 65)

In [130]: for value in d.values():
              print(type(value))
          <class 'str'>
          <class 'str'>
          <class 'str'>
          <class 'int'>

本文截選自《Python金融大數據分析》第2版

本書總計分為5部分,共21章。第1部分介紹了Python在金融學中的應用,其內容涵蓋了Python用於金融行業的原因、Python的基礎架構和工具,以及Python在計量金融學中的一些具體入門實例;第2部分介紹了Python的基礎知識以及Python中非常有名的庫NumPy和pandas工具集,還介紹了面向對象編程;第3部分介紹金融數據科學的相關基本技術和方法,包括數據可視化、輸入/輸出操作和數學中與金融相關的知識等;第4部分介紹Python在算法交易上的應用,重點介紹常見算法,包括機器學習、深度神經網絡等人工智慧相關算法;第5部分講解基於蒙特卡洛模擬開發期權及衍生品定價的應用,其內容涵蓋了估值框架的介紹、金融模型的模擬、衍生品的估值、投資組合的估值等知識。

本書適合對使用Python進行大數據分析和處理感興趣的金融行業開發人員閱讀。

關鍵字: