python學習筆記比較全(中)

continue 語句

continue 語句被用來告訴Python跳過當前循環塊中的剩餘語句,然後 繼續 進行下一輪循環。

break 語句 和 continue 語句 對於 while 循環 和 for 循環 都有效。

例(2.x寫法):

while True:

s = raw_input('Enter something : ')

if s == 'quit':

break

if len(s) < 3:

print 'Input is not of sufficient length'

continue

# Do other kinds of processing here...

print 'Length of the string is', len(s)

例(3.x寫法):

while True:

s = input('Enter something : ') # 3.x用input()代替raw_input(),且會獲取結尾輸入的換行符

s = s[:-1] # 去掉結尾的換行符

if s == 'quit':

break

if len(s) < 3:

print('Input is not of sufficient length')

continue

# Do other kinds of processing here...

print('Length of the string is', len(s))

函數:

定義函數

函數通過def關鍵字定義。

def關鍵字後跟一個函數的 標識符 名稱,然後跟一對圓括號。圓括號之中可以包括一些變量名,該行以冒號結尾。

接下來是一塊語句,它們是函數體。

例:

def sayHello():

print('Hello World!') # block belonging to the function

sayHello() # call the function

函數形參

函數中的參數名稱為 形參 而你提供給函數調用的值稱為 實參 。

局部變量

當你在函數定義內聲明變量的時候,它們與函數外具有相同名稱的其他變量沒有任何關係,即變量名稱對於函數來說是 局部 的。

這稱為變量的 作用域 。所有變量的作用域是它們被定義的塊,從它們的名稱被定義的那點開始。

例:

x = 50

def func(x):

print('x is', x)

x = 2

print('Changed local x to', x) # 打印: 2

func(x)

print('x is still', x) # 打印: 50, 值沒有變

global 語句

如果要為一個定義在函數外的變量賦值,那麼你就得告訴Python這個變量名不是局部的,而是 全局 的。使用global語句完成這一功能。

沒有global語句,是不可能為定義在函數外的變量賦值的。

你可以使用定義在函數外的變量的值(假設在函數內沒有同名的變量)。然而,應避免這樣做,因為這降低程序的可讀性,不清楚變量在哪裡定義的。

使用global語句可以清楚地表明變量是在外面的塊定義的。

注:可以使用同一個global語句指定多個全局變量。例如 global x, y, z。

例:

def func():

global x

print('x is', x)

x = 2

print('Changed local x to', x) # 打印: 2

x = 50

func()

print('Value of x is', x) # 打印: 2, 值被改變了

默認參數值

如果希望一些參數是 可選 的,這些參數可使用默認值。

可以在函數定義的形參名後加上賦值運算符(=)和默認值,從而給形參指定默認參數值。

注意,默認參數值應該是一個參數。

例:

def say(message, times = 2):

print(message * times)

say('Hello ') # 打印:Hello Hello

say('World ', 5) # 打印:World World World World World

重要:

只有在形參表末尾的那些參數可以有默認參數值,即不能在聲明函數形參的時候,先聲明有默認值的形參而後聲明沒有默認值的形參。

這是因為賦給形參的值是根據位置而賦值的。例如,def func(a, b=5)是有效的,但是def func(a=5, b)是 無效 的。

關鍵參數

如果某個函數有許多參數,而你只想指定其中的一部分,那麼可以通過命名來為這些參數賦值

——這被稱作 關鍵參數 ——使用名字(關鍵字)而不是位置來給函數指定實參。

這樣做有兩個優勢:

一、由於我們不必擔心參數的順序,使用函數變得更加簡單了。

二、假設其他參數都有默認值,我們可以只給我們想要的那些參數賦值。

例:

def func(a, b=5, c=10):

print('a is', a, 'and b is', b, 'and c is', c)

func(3, 7) # 參數a得到值3,參數b得到值7,而參數c使用默認值10。

func(25, c=24) # 根據實參的位置,變量a得到值25。根據命名,即關鍵參數,參數c得到值24。變量b根據默認值,為5。

func(c=50, a=100) # 使用關鍵參數來完全指定參數值。a得到值100,c得到值50。變量b根據默認值,為5。

return 語句

return語句用來從一個函數 返回 即跳出函數。我們也可選從函數 返回一個值 。

例:

def maximum(x, y):

if x > y:

return x

else:

return y

print(maximum(2, 3)) # 打印 3

None

None 是Python中表示沒有任何東西的特殊類型(相當於java的 null)。例如,如果一個變量的值為None,可以表示它沒有值。

注意:函數沒有返回值的,等價於最後返回return None。通過運行print someFunction(),你可以明白這一點。

例:

def someFunction():

# pass語句在Python中表示一個空的語句塊。它後面的代碼會照常運行。

pass

print(someFunction())

DocStrings

DocStrings:文檔字符串。它是一個重要的工具,幫助你的程序文檔更加簡單易懂,應該儘量使用它。甚至可以在程序運行的時候,從函數恢復文檔字符串!

在函數的第一個邏輯行的字符串是這個函數的 文檔字符串 。注意,DocStrings也適用於模塊和類。

文檔字符串的慣例是一個多行字符串,它的首行以大寫字母開始,句號結尾。第二行是空行,從第三行開始是詳細的描述。 強烈建議遵循這個慣例。

例:

def printMax(x, y):

'''Prints the maximum of two numbers.

The two values must be integers.'''

x = int(x) # convert to integers, if possible

y = int(y)

if x > y:

print(x, 'is maximum')

else:

print(y, 'is maximum')

printMax(3, 5) # 打印: 5 is maximum

print(printMax.__doc__) # 打印: Prints the maximum ... must be integers.

注:

使用__doc__(注意是兩個下劃線)調用printMax函數的文檔字符串屬性。請記住Python把 每一樣東西 都作為對象,包括這個函數。

Python中help()函數即是使用DocStings的了,它只是抓取函數的__doc__屬性,然後整潔地展示給你。可以對上面的函數嘗試一下: help(printMax)。記住按q退出help。

自動化工具也可以以同樣的方式從你的程序中提取文檔。因此強烈建議你對你所寫的任何正式函數編寫文檔字符串。

函數屬性 func_*

在Python 2裡,函數的裡的代碼可以訪問到函數本身的特殊屬性。在Python 3裡,為了一致性,這些特殊屬性被重新命名了。

Python 2 與 Python 3 的比較

Python 2 Python 3 說明

① a_function.func_name a_function.__name__ # 包含了函數的名字。

② a_function.func_doc a_function.__doc__ # 包含了在函數源代碼裡定義的文檔字符串(docstring)。

③ a_function.func_defaults a_function.__defaults__ # 是一個保存參數默認值的元組。

④ a_function.func_dict a_function.__dict__ # 一個支持任意函數屬性的名字空間。

⑤ a_function.func_closure a_function.__closure__ # 一個由cell對象組成的元組,包含了函數對自由變量(free variable)的綁定。

⑥ a_function.func_globals a_function.__globals__ # 一個對模塊全局名字空間的引用,函數本身在這個名字空間裡被定義。

⑦ a_function.func_code a_function.__code__ # 一個代碼對象,表示編譯後的函數體。

模塊:

如果要在其他程序中重用很多函數,那麼你該使用模塊。

模塊基本上就是一個包含了所有你定義的函數和變量的文件。

為了在其他程序中重用模塊,模塊的文件名必須以.py為擴展名。

sys模塊(標準庫模塊)

sys模塊包含了與Python解釋器和它的環境有關的函數。

例:

import sys # 輸入 sys模塊。基本上,這句語句告訴Python,我們想要使用這個模塊。

print('The command line arguments are:')

# 打印調用文件的命令行參數

for i in sys.argv:

print(i)

print('\\nThe PYTHONPATH is', sys.path)

輸出:

$ python using_sys.py we are arguments

The command line arguments are:

using_sys.py

we

are

arguments

The PYTHONPATH is ['/home/swaroop/byte/code', '/usr/lib/python23.zip',

'/usr/lib/python2.3', '/usr/lib/python2.3/plat-linux2',

'/usr/lib/python2.3/lib-tk', '/usr/lib/python2.3/lib-dynload',

'/usr/lib/python2.3/site-packages', '/usr/lib/python2.3/site-packages/gtk-2.0']

注:

執行 import sys 語句的時候,它在 sys.path 變量中所列目錄中尋找 sys.py 模塊。

如果找到了這個文件,這個模塊的主塊中的語句將被運行,然後這個模塊將能夠被你使用。

注意,初始化過程僅在我們 第一次 輸入模塊的時候進行。另外,“sys”是“system”的縮寫。

腳本的名稱總是sys.argv列表的第一個參數。所以,在這裡,'using_sys.py'是sys.argv[0]、'we'是sys.argv[1]。

sys.path包含輸入模塊的目錄名列表。

可以觀察到sys.path的第一個字符串是空的——這個空的字符串表示當前目錄也是sys.path的一部分,這與PYTHONPATH環境變量是相同的。

這意味著你可以直接輸入位於當前目錄的模塊。否則,你得把你的模塊放在sys.path所列的目錄之一。

另外:

sys.exit() # 程序結束

sys.stdin、 sys.stdout 和 sys.stderr 分別對應你的程序的標準輸入、標準輸出和標準錯誤流。

字節編譯的.pyc文件

輸入一個模塊相對來說是一個比較費時的事情,所以Python做了一些技巧,以便使輸入模塊更加快一些。

一種方法是創建 字節編譯的文件,這些文件以.pyc作為擴展名。另外,這些字節編譯的文件也是與平臺無關的。

當你在下次從別的程序輸入這個模塊的時候,.pyc文件是十分有用的——它會快得多,因為一部分輸入模塊所需的處理已經完成了。

from ... import 語句

如果你想要直接輸入 argv 變量到你的程序中(避免在每次使用它時打sys.),那麼你可以使用 from sys import argv 語句。

如果你想要輸入所有 sys 模塊使用的名字,那麼你可以使用 from sys import *語句。

這對於所有模塊都適用。

注意:

1.使用 from package import item 方式導入包時,這個子項(item)既可以是包中的一個子模塊(或一個子包),也可以是包中定義的其它命名,像函數、類或變量。

import 語句首先核對是否包中有這個子項,如果沒有,它假定這是一個模塊,並嘗試加載它。如果沒有找到它,會引發一個 ImportError 異常。

2.使用像 import item.subitem.subsubitem 這樣的語句時,這些子項必須是包,最後的子項可以是包或模塊,但不能是前面子項中定義的類、函數或變量。

3.應該避免使用 from...import 而使用 import 語句,因為這樣可以使你的程序更加易讀,也可以避免名稱的衝突。

import ... as

為 import 的模塊起一個簡稱。如: import cPickle as p

起簡稱後,下面的語句即可使用簡稱,如原本的 cPickle.dump() 可寫成 p.dump()

模塊的 __name__

每個模塊都有一個名稱,在模塊中可以通過語句來找出模塊的名稱。

這在一個場合特別有用——就如前面所提到的,當一個模塊被第一次輸入的時候,這個模塊的主塊將被運行。

假如我們只想在程序本身被使用的時候運行主塊,而在它被別的模塊輸入的時候不運行主塊,我們該怎麼做呢?這可以通過模塊的__name__屬性完成。

每個Python模塊都有它的__name__,如果它是'__main__',這說明這個模塊被用戶單獨運行,我們可以進行相應的恰當操作。

例:

# Filename: using_name.py

if __name__ == '__main__':

print('This program is being run by itself')

else:

print('I am being imported from another module')

輸出:

$ python using_name.py

This program is being run by itself

$ python

>>> import using_name

I am being imported from another module

自定義模塊

每個Python程序也是一個模塊。

模塊,例:

# Filename: mymodule.py

def sayhi():

print('Hi, this is mymodule speaking.')

version = '0.1'

# End of mymodule.py

上面是一個 模塊 的例子。你已經看到,它與我們普通的Python程序相比並沒有什麼特別之處。

記住這個模塊應該被放置在我們輸入它的程序的同一個目錄中,或者在 sys.path 所列目錄之一。

用例1:

import mymodule

mymodule.sayhi()

print('Version', mymodule.version)

注:函數和成員都以點號來使用。

用例2: 使用from..import語法的版本。

from mymodule import sayhi, version # 或者寫: from mymodule import *

sayhi()

print('Version', version)

包(Packages)

包通常是使用用“圓點模塊名”的結構化模塊命名空間。例如, A.B 表示名為"A" 的包中含有名為"B"的子模塊。

使用圓點模塊名保存不同類庫的包可以避免模塊之間的命名衝突。(如同用模塊來保存不同的模塊架構可以避免變量之間的命名衝突)

包目錄必須要有一個 __init__.py 文件的存在;這是為了防止命名衝突而無意中在隨後的模塊搜索路徑中覆蓋了正確的模塊。

最簡單的情況下, __init__.py 可以只是一個空文件,不過它也可能包含了包的初始化代碼,或者設置了 __all__ 變量。

dir()函數

使用內建的dir函數來列出模塊定義的標識符。標識符有函數、類和變量。

當你為 dir()提供一個模塊名的時候,它返回模塊定義的名稱列表。如果不提供參數,它返回當前模塊中定義的名稱列表。

$ python

>>> import sys

>>> dir(sys) # get list of attributes for sys module

['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__',

'__stdin__', '__stdout__', '_getframe', 'api_version', 'argv',

'builtin_module_names', 'byteorder', 'call_tracing', 'callstats',

'copyright', 'displayhook', 'exc_clear', 'exc_info', 'exc_type',

'excepthook', 'exec_prefix', 'executable', 'exit', 'getcheckinterval',

'getdefaultencoding', 'getdlopenflags', 'getfilesystemencoding',

'getrecursionlimit', 'getrefcount', 'hexversion', 'maxint', 'maxunicode',

'meta_path','modules', 'path', 'path_hooks', 'path_importer_cache',

'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setdlopenflags',

'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout',

'version', 'version_info', 'warnoptions']

>>> dir() # get list of attributes for current module

['__builtins__', '__doc__', '__name__', 'sys']

>>>

>>> a = 5 # create a new variable 'a'

>>> dir()

['__builtins__', '__doc__', '__name__', 'a', 'sys']

>>>

>>> del a # delete/remove a name; 這個得留意

>>>

>>> dir()

['__builtins__', '__doc__', '__name__', 'sys']

>>>

數據結構

可以處理一些 數據 的 結構 。或者說,它們是用來存儲一組相關數據的。

在Python中有三種內建的數據結構——列表、元組和字典。

列表(list, 有的語言稱為:數組)

是處理一組有序項目的數據結構,即你可以在一個列表中存儲一個 序列 的項目。

列表中的項目應該包括在方括號中,每個項目之間用逗號分割。

可以添加、刪除或是搜索列表中的項目。列表是 可變的 數據類型。

列表對象定義的所有方法可以通過 help(list) 獲得完整的知識。我比較習慣稱它為“數組”。

例:

shoplist = ['apple', 'mango', 'carrot', 'banana']

#查看長度

print('I have', len(shoplist),'items to purchase.')

#遍歷

print('These items are:', end=' ') # 注意這行的結尾,打印時可以不換行,python 2.x應該用逗號結尾

for item in shoplist:

print(item, end=' ') # python 2.x 此行應該寫:“print item,”

#添加

print('\\nI also have to buy rice.')

shoplist.append('rice')

print('My shopping list is now:', shoplist)

#排序

print('I will sort my list now')

shoplist.sort()

print('Sorted shopping list is:', shoplist)

#刪除,以及使用下標

print('The first item I will buy is:', shoplist[0])

olditem = shoplist[0]

del shoplist[0]

print('I bought the', olditem)

print('My shopping list is now:', shoplist)

#多維列表時,保存的對象只是引用

newlist = ['waa','dd']

shoplist.append(newlist)

print('My shopping list is now:', shoplist)

del newlist[0]

print('My shopping list is now', shoplist)

# 刪除重複, 用 set (對元組也可以這樣寫)

L = [1,1,1,2,2]

print(list(set(L))) # 打印:[1, 2]

l = [(1, 2), (1, 2), 3, 5, 4, 3, 4, (1, 2), 0, 5]

l = list(set(l))

print(l) # 打印: [(1, 2), 0, 3, 4, 5]

# 複製列表(淺拷貝)

c = shoplist[:]

# 複製(深拷貝)

import copy

c = copy.deepcopy(shoplist)

元組(tuple)

元組和列表十分類似,只不過元組和字符串一樣是 不可變的 即你不能修改元組。

元組通過圓括號中用逗號分割的項目定義。

元組通常用在使語句或用戶定義的函數能夠安全地採用一組值的時候,即被使用的元組的值不會改變。

如果你想要知道元組對象定義的所有方法,可以通過 help(tuple) 獲得完整的知識。

例:

#一維元組

zoo = ('wolf', 'elephant', 'penguin')

print('Number of animals in the zoo is %s' % len(zoo)) # 打印: 3

newlist = ['waa','dd']

#多維元組

new_zoo = ('monkey', 'dolphin', zoo, newlist)

print('Number of animals in the new zoo is %s' % len(new_zoo)) # 打印: 3

print('All animals in new zoo are %s' % str(new_zoo)) # 打印: ('monkey','dolphin',('wolf','elephant','penguin'),['waa','dd'])

print('Animals brought from old zoo are %s' % str(new_zoo[2])) # 打印: ('wolf', 'elephant', 'penguin')

print('Last animal brought from old zoo is %s' % new_zoo[2][2]) # 打印: penguin

#多維元組時,保存的對象只是引用

del newlist[0]

print('new_zoo is now:' + str(new_zoo) ) # 打印: ('monkey','dolphin',('wolf','elephant','penguin'),['dd'])

注意:含有0個或1個項目的元組

一個空的元組(含有0個項目)由一對空的圓括號組成,如myempty = ()。

含有單個元素的元組必須在第一個(唯一一個)項目後跟一個逗號。如: singleton = (2 , )。

如果小括號裡面只有唯一一個項目,而這個項目後面又沒有跟一個逗號的話,Python會認為它是一個表達式。

字典(dict, 有的語言稱為:json)

字典把鍵(名字)和值(詳細情況)聯繫在一起。

注意,鍵必須是唯一的,且只能使用不可變的對象(比如字符串)來作為字典的鍵,但字典的值沒有此限制。應該說只能使用簡單的對象作為鍵。

鍵值對在字典中以這樣的方式標記:d = {key1 : value1, key2 : value2 }。

鍵值對用冒號分割,而各個對用逗號分割,所有這些都包括在花括號中。

記住字典中的鍵/值對是沒有順序的。如果要一個特定的順序,那麼應該在使用前自己對它們排序。

字典是dict類的實例/對象,可以用 help(dict) 來查看其屬性和函數。

例:

ab = { 'Swaroop': 'swar',

'Larry' : 'larry',

'Spammer': 'spammer'

}

print(ab) # 打印: {'Swaroop':'swar', 'Larry':'larry', 'Spammer':'spammer'}

print("Swaroop's address is %s" % ab['Swaroop']) # 打印: swar

# 添加值,或者設值

ab['Guido'] = 'guido'

# 刪除值

del ab['Spammer']

# ab.pop('Spammer') # 也可以用 pop 來刪除,但建議後面的這種寫法,避免沒有這個鍵時會報錯: ab.pop('Spammer', None)

print('\\nThere are %d contacts in the address-book\\n' % len(ab)) # 打印: 3

# 遍歷(這寫法得留意)

for name, address in ab.items():

print('Contact %s at %s' % (name, address))

# 包含key

if 'Guido' in ab: # 或者寫: if ab.has_key('Guido'):

print("\\nGuido's address is %s" % ab['Guido'])

# 原字典上創建新字典

print(ab) # 打印: {'Swaroop':'swar', 'Larry':'larry', 'Guido':'guido'}

dd = dict(ab, slug_field='slug', test=5) # 創建新字典,字典作為參數的只能放第一個,其餘不能再是字典;字典參數可省略

print(dd) # 打印: {'Swaroop':'swar', 'test':5, 'slug_field':'slug', 'Larry':'larry', 'Guido':'guido'}

# 建議的取值方法

print( ab['test'] ) # 這樣取值,當字典裡面沒有對應的key時會報錯:“KeyError”

print( ab.get('test', 'default_value') ) # get取值,當字典裡面沒有對應的key時可取後面的預設值,預設值是可選的(默認是 None)

# 所有的鍵和值

print(ab.keys()) # 所有的鍵

print(ab.values()) # 所有的值

# 複製(淺拷貝)

print(ab.copy())

# 複製(深拷貝)

import copy

c = copy.deepcopy(ab)

序列

列表、元組和字符串都是序列,序列的兩個主要特點是“索引”操作符和“切片”操作符。

索引操作符讓我們可以從序列中抓取一個特定項目。(即使用下標)

切片操作符讓我們能夠獲取序列的一個切片,即一部分序列。(即在下標的中括號裡面使用冒號)

例:

shoplist = ['apple', 'mango', 'carrot', 'banana']

# Indexing or 'Subscription' operation

print('Item 0 is %s' % shoplist[0])

print('Item 3 is %s' % shoplist[3])

print('Item -1 is %s' % shoplist[-1]) # 打印:banana 即倒數第一個

print('Item -2 is %s' % shoplist[-2]) # 打印:carrot 即倒數第二個

# Slicing on a list

print('Item 1 to 3 is %s' % shoplist[1:3]) # 打印:['mango', 'carrot'] 即下標[1]到[3],包括開始但不包括結束

print('Item 2 to end is %s' % shoplist[2:]) # 打印:['carrot', 'banana'] 即下標[2]到結束,包括最後一個

print('Item 1 to -1 is %s' % shoplist[1:-1]) # 打印:['mango', 'carrot'] 即下標[1]到[-1],包括開始但不包括結束

print('Item start to end is %s' % shoplist[:]) # 打印整個列表,跟直接寫“shoplist”效果一樣

# Slicing on a string (string與列表有同樣的操作,)

name = 'swaroop'

print('characters 1 to 3 is %s' % name[1:3]) # 打印:wa

print('characters 2 to end is %s' % name[2:]) # 打印:aroop

print('characters 1 to -1 is %s' % name[1:-1]) # 打印:waroo

print('characters start to end is %s' % name[:]) # 打印:swaroop 跟直接寫這個字符串一樣

參考(引用)

當你創建一個對象並給它賦一個變量的時候,這個變量僅僅 參考 那個對象,而不是表示這個對象本身!

也就是說,變量名指向你計算機中存儲那個對象的內存。

這被稱作名稱到對象的綁定。

例:

shoplist = ['apple', 'mango', 'carrot', 'banana']

mylist = shoplist # mylist 只是對象的另一個名稱,他們指向相同的內存空間

del shoplist[0]

# 他們此時打印相同的內容,都少了'apple'

print('shoplist is', shoplist)

print('mylist is', mylist)

# 深拷貝,複製成另一個對象(得記住用切片操作符來取得拷貝)

mylist = shoplist[:] # make a copy by doing a full slice

del mylist[0] # remove first item

# 注意,現在他們打印出不同的內容

print('shoplist is', shoplist)

print('mylist is', mylist)

列表綜合

通過列表綜合,可以從一個已有的列表導出一個新的列表。

[返回值 for 元素 in 列表 if 條件] 比如 [num for num in xrange(100) if num%2==0] 返回0~99之間的偶數列表

# 例如,你有一個數的列表,而你想要得到一個對應的列表,使其中所有大於2的數都是原來的2倍。對於這種應用,列表綜合是最理想的方法。

listone = [2, 3, 4]

listtwo = [2*i for i in listone if i > 2] # 為滿足條件(if i > 2)的數指定了一個操作(2*i),從而導出一個新的列表。

print(listtwo) # 打印: [6, 8]

ls=[1,3,5,7] # reduce 在python3去掉了

print(reduce(lambda x,y:x+y,ls)) # 計算過程就是 1+3=4 然後4+5得到結果9,再加7,以此類推,最後返回最終計算的結果(總和);打印:16

# 將字典的key,value倒過來的寫法:

a_dict = {'a': 1, 'b': 2, 'c': 3}

# python3 的寫法:

b_dict = {value:key for key, value in a_dict.items()}

# python2 時的寫法:

b_dict = {}

for key, value in a_dict.iteritems():

b_dict[value] = key

print(b_dict) # key與value翻轉,打印: {1:'a', 2:'b', 3:'c'}

說明:

注意原來的列表並沒有發生變化。

在很多時候,我們都是使用循環來處理列表中的每一個元素,而使用列表綜合可以用一種更加精確、簡潔、清楚的方法完成相同的工作。

小心 list 的 += 操作(python2時可以用,python3不可以再這樣用)

集合

Python3 開始有這寫法,跟之前的差不多,只是用大括號括起來,如: a = {1, 'aa', 3, 5, 6}

集合同樣可以使用綜合計算,如: a = {x for x in range(10) if x % 2 == 0}

成員測試 in, not in

檢查是否包含有此內容,返回 True 或者 False, 例如:

# 1.對字符串

if 'a' in 'Swaroop':

print('Yes, it contains the string "a"')

# 2.對集合(列表、元組和字典)

if 'genre' in ('genre', 'jazz'):

print('Yes, it contains the genre')

print('genre' in ('genre', 'jazz')) # 元組,打印: True

print('genre' in ['genre', 'jazz']) # 列表,打印: True

print('genre' in {'genre':'sss', 'jazz':'dddd'}) # 字典,檢查key,打印: True

print('sss' in {'genre':'sss', 'jazz':'dddd'}) # 字典,打印: False

排序

1.sort方法

Python語言內置了sort方法,可以很方便地對某個List進行排序

例如:

L = [6, 5, 1, 3, 4, 2]

L.sort()

print(L) # 打印:[1, 2, 3, 4, 5, 6]

li=[(2,'a'),(4,'b'),(1,'d')]

li.sort() # 元組列表排序

print(li) # 打印: [(1, 'd'), (2, 'a'), (4, 'b')]

2.自定義排序(例如,按關鍵詞的權重排序,按人的年齡排序,等等)

若List中每個元素都是2-tuple,tuple中第一個元素為String類型的keyword,第二個元素為該字符串對應的權重(int類型),希望按照權重排序(從高到低),則可以這樣:

L = [('b', 1), ('a', 0), ('c', 2), ('d', 3)]

# L.sort(lambda E1, E2: -cmp(E1[1], E2[1])) # cmp函數里面是需比較的兩個值,負號表示倒序。(python2 的寫法)

L.sort(key=lambda d:-d[1]) # Python3的寫法,由於去掉了cmp()函數,得傳入key參數; python2也可以這樣用;負號表示倒序

print(L) # 打印:[('d', 3), ('c', 2), ('b', 1), ('a', 0)]

3.dict排序

對字典的排序,因為每一個項包括一個鍵值對,所以要選擇可比較的鍵或值進行排序

sorted(iterable[, cmp[, key[, reverse]]])

# cmp 和 key 一般使用 lambda

如:

d={"ok":1,"no":2}

# 對字典按鍵排序,用元組列表的形式返回

print(sorted(d.items(), key=lambda a:a[0])) # 打印: [('no', 2), ('ok', 1)]

print(sorted(d)) # 打印:['no', 'ok']

print(d) # 原字典並未改變,打印:{'ok':1, 'no':2}

# 對字典按值排序,用元組列表的形式返回

print(sorted(d.items(), key=lambda d:d[1])) # 打印:[('ok', 1), ('no', 2)]

# 排序後再轉成字典,就無法再保證排序了

b = sorted(d.items(), key=lambda v:v[0])

print(b) # 打印: [('no', 2), ('ok', 1)]

print(dict(b)) # (排序又亂了)打印: {'ok': 1, 'no': 2}

4.類的排序

class test:

def __init__(self,a,b):

self.a = a

self.b = b

test1 = test(5,25)

test2 = test(50,35)

test3 = test(10,15)

tests = [test1, test2, test3]

# 以 cmp 來指定排序方式, python3不可以這樣寫(沒有cmp參數及cmp函數)

result = sorted(tests,cmp = lambda x,y: cmp(x.a, y.a))

# 遍歷排序結果,結果是已排序的: a:5 a:10 a:50

for item in result:

print("a:%s" % item.a)

# 以 key 來排序,結果也是可以的

result2 = sorted(tests,key = lambda d:d.a)

for item in result2:

print("a:%s" % item.a)

# 遍歷原資料,原資料的順序沒有改變

for item in tests:

print("a:%s" % item.a)

5.注意:

python3 由於去掉了 cmp() 函數,可以用“(a > b) - (a < b)”代替“ cmp(a, b) ”

6.冒泡算法,如下:

num = [23,2,3,6,18,9,33,13,24,19]

for i in range(len(num)-1):

for j in range(len(num)-i-1):

if (num[j] > num[j+1]):

num[j], num[j+1] = num[j+1], num[j] # 置換,這樣寫比較簡便,不需再用臨時變量

print(num)

綜合實例:

在Python中對列表,元組,字典等內置的數據結構的處理是很方便的事情,python借鑑了Lisp中的很多函數式計算的方法來處理列表,可以極大的簡化我們的代碼。

1. set(): 將元組,列表 轉化成沒有重複項的集合

2. list(): 將集合,元組轉化成列表

3. tuple(): 將集合,列表轉化成元組

4. map(func,list):將list的每一個元素傳遞給func的函數,這個函數有一個參數,且返回一個值,map將每一次調用函數返回的值組成一個新列表返回

5. filter(func,list):將list的每一個元素傳遞給func的函數,這個函數有一個參數,返回bool類型的值,filter將返回True的元素組成新列表返回

6. reduce(func,list):將list的元素,挨個取出來和下一個元素通過func計算後將結果和再下一個元素繼續計算

一、列表去重

ls = [1,3,2,5,2,1,3,4,6]

ls = list(set(ls)) # 最簡單的列表去除重複

L = [1, 8, 3, 4, 6, 2, 3, 4, 5]

kk = [x for x in L if x not in locals()['_[1]']] # 保留原順序的去除重複,只有 2.6 上可以, 2.7 以上版本不能這樣寫

# '_[1]' 是個內部臨時變量,可查看: [x for x, y in locals().items()]

二、假如有列表:

books = [

{"name":"C#從入門到精通", "price":23.7, "store":"卓越"},

{"name":"ASP.NET高級編程", "price":44.5, "store":"卓越"},

{"name":"C#從入門到精通", "price":24.7, "store":"噹噹"},

{"name":"ASP.NET高級編程", "price":45.7, "store":"噹噹"},

{"name":"C#從入門到精通", "price":26.7, "store":"新華書店"},

{"name":"ASP.NET高級編程", "price":55.7, "store":"新華書店"},

]

2.1 求《ASP.NET高級編程》價格最便宜的店:

storename=min([b for b in books if b['name']=="ASP.NET高級編程"],key=lambda b:b['price'])["store"]

過程:先用列表解析取出《ASP.NET高級編程》的列表,通過min函數,比較字典的price鍵獲取price最小的項

2.2 求在新華書店購買兩本書一樣一本要花的錢:

price=sum([b['price'] for b in books if b['store']=="新華書店"])

2.3 求列表中有那幾本書:

booknames=list(set([b['name'] for b in books]))

2.4 列表裡的書都打5折:

books=map(lambda b:dict(name=b['name'],price=b['price']*0.5,store=b['store']),books)

2.5 《C#從入門到精通》的平均價格:

avg=(lambda ls:sum(ls)/len(ls))([b['price'] for b in books if b['name']=="C#從入門到精通"])

2.6 求每本書的平均價格:

book_avg=map(lambda bookname:dict(name=bookname,avg=(lambda ls:sum(ls)/len(ls))([b['price'] for b in books if b['name']==bookname])),list(set([b['name'] for b in books])))

這段代碼放在一行比較難看懂,但是格式化一下就很好懂了,構建的過程如下:

step1: 要求每本書的平均價格,首先要得到共有幾本書,方法見2.3,得到去重的書名列表

list(set([b['name'] for b in books])) #去重後的書名列表

step2: 要求每一本書的均價,需要將計算均價的函數映射到每一本書上,於是

map(

#計算均價的函數,

list(set([b['name'] for b in books])) #去重後的書名列表

)

step3: 加入計算單本書均價的函數,參考2.5的方法,由於只用一行,所以用lambda來搞定:

func=lambda bookname:(lambda ls:sum(ls)/len(ls))([b.price for b in books if b['name']==bookname])

step4: 將計算單本均價的lambda函數加入map中,得到最終結果:

經過格式化後的結果,前面的單行代碼可以格式化為下面容易閱讀的形式

book_avg=map(

lambda bookname:

dict(

name = bookname,

# 計算單本書均價的函數

avg = (lambda ls:sum(ls)/len(ls)) ([b['price'] for b in books if b['name']==bookname])

),

#去重後的書名列表

list(

set(

[b['name'] for b in books]

)

)

)

在函數中接收元組和列表(函數的參數數量可以變動,即可變長參數)

當要使函數接收元組或字典形式的參數的時候,有一種特殊的方法,它分別使用*和**前綴。

這種方法在函數需要獲取可變數量的參數的時候特別有用。

而且,使用*和**前綴的參數還可以傳遞給其它函數。

例:

# 由於在args變量前有*前綴,所有多餘的函數參數都會作為一個元組存儲在args中

def sum(message, *args):

'''Return the sum of each argument.'''

total = 0

# 除了用循環,也可以用下標來讀取參數,如: args[0]

for i in args:

total += i

print (str(type(args)) + ' ' + message + ":" + str(total))

sum2(args) # 這樣傳過去的 args 是一個元組;打印如: ((3, 5.5),)

sum2(*args) # 這樣傳過去的 *args 表示多個參數;打印如:(3, 5.5)

def sum2(*args):

print(args)

sum('hight', 3, 5.5) # 打印: <type> hight:8.5/<type>

sum('weight', 10) # 打印: <type> weight:10/<type>

# 函數參數接收字典用法。使用的是**前綴,多餘的參數則會被認為是一個字典的鍵/值對。

def printDict(message, **args):

print(str(type(args)) + ' ' + message + ':' + str(args))

printDict2(args = args) # 可這樣,把 args 當做一個值(裡面是字典),傳過去;打印如: {'args': {'a': 3, 'b': 'dd'}}

printDict2(**args) # 也可這樣,把 **args 看做傳過來的多個鍵/值對,傳過去;打印如:{'a': 3, 'b': 'dd'}

def printDict2(**args):

print(args)

# 注意:參數為字典時,參數裡面必須使用等號,否則運行出錯

printDict('hight', a=3, b='dd') # 打印: <type> hight:{'a': 3, 'b': 'dd'}/<type>

# 可以混合使用*和**前綴的參數, 但是必須 *args 在前, **args 在後,否則編譯不通過

def printMul(message, *args1, **args2):

print(message + ' args1:' + str(args1) + ' args2:' + str(args2))

printMul('hello', 5, 4, a=2, b=3) # 打印: hello args1:(5, 4) args2:{'a': 2, 'b': 3}

面向對象的編程

面向過程的編程:根據操作數據的函數或語句塊來設計程序的。

面向對象的編程:把數據和功能結合起來,用稱為對象的東西包裹起來組織程序的方法。

類和對象是面向對象編程的兩個主要方面。“類”創建一個新類型,而“對象”是這個類的實例。

域:屬於一個對象或類的變量。

方法:屬於類的函數,被稱為類的方法。

域和方法可以合稱為類的屬性。

域有兩種類型——屬於每個實例/類的對象或屬於類本身。它們分別被稱為實例變量和類變量。

類使用class關鍵字創建。類的域和方法被列在一個縮進塊中。

python學習筆記比較全(中)


分享到:


相關文章: