讀《簡明Python教程》筆記:
本書的官方網站是www.byteofpython.info
安裝就不說了,網上很多,這里就記錄下我在安裝時的問題,首先到python官網下載,選好安裝路徑安裝好后,一定要配置環境變量,詳細呢可以看武老師的博客(我的python編程入門老師雖然他不認識我,我也不認識他)。
重要
在你的程序中合理地使用注釋以解釋一些重要的細節——這將有助於你的程序的讀者輕松地理
解程序在干什么。記住,這個讀者可能就是6個月以后的你!
可執行的python程序(linux下):
$ chmod a+x hello_world.py
$ ./hello_world.py
$ 輸出程序的執行結果
chmod命令用來改變文件模式,給系統中所有用戶這個源文件的執行權限,然后就可以直接通過指定源文件的位置來執行程序,使用./提示程序位於當前目錄。
也可以把.py去掉直接執行文件,因為系統要使用源文件第一行指定的解釋器來執行該文件。
只要知道文件的確切位置,你就可以運行程序——但是如果你希望你的程序可以從各個位置運行,你可以把你的程序保存在PATH環境變量中的目錄之一,系統會自動在PATH中的目錄里尋找你要執行的文件。
$echo $PATH
/opt/mono/bin/:/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/home/swaroop/bin
$cp hello_world.py /home/swaroop/bin/hello_world
$hello_world
程序執行的結果
用echo命令顯示PATH變量,用$給變量名加前綴以向shell表示我們需要這個變量的值。我們看到的/home/swaroop/bin是PATH變量中的目錄之一。swaroop是在系統中使用的用戶名。你可以把你選擇的目錄添加到PATH變量中——這可以通過運行PATH=$PATH :/home/swaroop/mydir完成。
當你想要在任何時間、任何地方運行你的程序,這個方法很有用。他就好像創造你自己的指令,如同cd或其他linux終端或DOS提示符命令那樣。
提示:(這個問題困惑我好久)
對於Python,程序、腳本或者軟件都是指同一個東西。
獲取幫助
help(str)括號內是你要查詢的數據類型。
linux下的操作:
如果想要獲取關於如print那樣操作符的幫助,那么你需要正確的設置PYTH ON DOCS環境變量。這可以在linux中輕松的通過env完成。
$ env PYRH ON DOCS=/usr/share/doc/python-docs-2.3.4/html/python
Python2.3.4(#1,0 ct26 2004,16:42:40)
[GCC 3.4.2 20041017(Red Hat3.4.2-6.fce)] on linux2
Type"help","copyright","cred its"or"license"form ore inform ation.
>>>help("print")
注意"print"要加引號。
一、字符串:
1、字符串:(字符串是字符的序列,是不可變的)
使用字符串的方式:
~ 單引號(’)
~ 雙引號(”) #"what's your name?"雙引號內使用單引號不用轉義符
~ 三引號('''或""") #'''what's your name? My name is "Guido's admisers", I like python.'''三引號中自由的使用單引號和雙引號
2、轉義符:
'what\'s your name?'如果沒有 \ python解釋器則找不到字符串的起止位置。
\\ 表示 \ 的意思
”how old are you?\
what's your name?"
上面的字符串則表示:行末的單獨的一個 \ 表示字符串在下一行繼續,而不是開始新的一行。
3、自然字符串:
r'what\'s your name? \n My name is Guido?'
這樣字符串里的轉義符就不會進行轉義處理了。
在處理正則表達式時一定要用"r"
二、變量:
1、變量名命名的規則:
~ 第一個字符必須是字母(大小寫均可)或者一個下划線('_')
~ 其他部分可以由字母(大小寫均可)、下划線('_')或樹脂(0-9)組成
~ 相同的變量名是區分大小寫的,例如name!=Name
~ 變量名中只能有以上說的方式內容組成
三、對象:
在Python中,在程序中用到的任何東西都叫對象。
四、邏輯行與物理行:
物理行是你在編寫程序時說看見的。邏輯行是Python解釋器看見的單個語句。如果在一個物理行使用多於一個邏輯行,就需要用分號(;)來特別標明這種用法。(;)表示一個邏輯行的結束。(盡量避免使用一個物理行存在多個邏輯行)
多個物理行可以寫一個邏輯行,例如:
s = "This is a string.\
This continues the sting."
print(s)
執行輸出:
This is a string.This continues the sting.
五、縮進:
在python中縮進決定語句的分組,同一層次的語句必須有相同的縮進,錯誤的縮進會引發錯誤。
在使用縮進時,空格和制表符不要混合使用,因為在跨平台操作時無法正常工作,在每個縮進層次使用單個制表符或者使用四個空格。
六、運算符與表達式:
運算符
運算符優先級
在運算中,python會優先計算下表中最下面的運算符,最好使用()圓括號來分組運算和操作數,使程序更加易讀。
在下表中列在同一行的運算符具有相同優先級。
下表是一個優先級的默認順序,如若想改變優先級的順序,則需使用圓括號。
結合規律:
具有相同優先級的運算符按照從左向右的順序計算。一些如賦值運算符那樣的運算符是由右向左結合的,即a=b=c被處理為a=(b=c)。
七、控制流:
if語句
if條件為真,執行if下的語句;如果if條件為假,處理另一塊elif語句;否則實行else塊,else從句是可選的。
注意:if、elif、else語句在結尾處包含一個冒號——我們通過他告訴python下面跟着一個語句塊。
#! usr/bin/env python # -*-coding:utf-8-*- name = input("what's your name?") if name == "VV": print("I love you!") elif name == "MM": print("Get out!") else: print("I don't know.")
while語句
如果條件為真,while語句允許重復執行一塊語句。所以while語句是循環語句。同時,也有一個可選的else從句
#!/usr/bin/env python # -*- coding:utf -8-*- while 1>2: print(123) break else: print(789)
for循環
for...in...是另外一個循環語句,它在以序列的對象上遞歸即逐一使用隊列中的每個項目。
#!/usr/bin/env python # -*- coding:utf -8-*- for i in range(1,5,2): print(i) else: print('MM')
range(1,5)生成序列[1,2,3,4],range的默認步長為1,給range提供第3個數,它將成為步長。例如:range(1,5,2)給出[1,3]。
else總是會在for循環結束后執行一次,除非遇到break
break語句:終止循環語句,一旦遇到立刻停止執行循環程序。
continue語句:終止后面的剩余語句,然后繼續進行下一輪循環。
八、函數
定義函數:
#!/usr/bin/env python # -*- coding:utf -8-*- def name(): #定義函數 pass #函數體 name() #執行函數
函數的參數:
函數的參數有形式參數和實際參數
定義時圓括號內的參數為形式參數,執行時圓括號內的參數為實際參數。
局部變量:
當你在函數定義內聲明變量的時候,它們與函數外具有相同名稱的其他變量沒有任何關系,即變量名稱對於函數來說是局部的。這稱為變量的作用域。所有變量的作用域是它們被定義的塊,從他們的名稱被定義的那點開始。
全局變量(global):
如果你想為一個定義在函數外的變量賦值,那么就得告訴python這個變量不是局部的,而是全局的。我們使用global語句完成這一功能。沒有global語句是不可能為定義在函數外的變量賦值的。
#!/usr/bin/env python # -*- coding:utf -8-*- MM = "alex" def name(): global MM print(MM) name()
默認參數值:
你可以在函數定義的形參后加上賦值運算符(=)和默認值,從而給形參指定默認參數值。
默認參數值應該是一個不可變的參數。
#!/usr/bin/env python # -*- coding:utf -8-*- def name(MM, VV="Lily"): pass name('TT')
關鍵參數:
不再依照傳入參數的順序來分配參數,而是使用名字來參入參數。
這樣做的兩個優勢:
~ 由於我們不必擔心參數的順序,使用函數變得更加簡單。
~ 假設其他參數都有默認值,我們可以只給我們想要的那些參數賦值。
#!/usr/bin/env python # -*- coding:utf -8-*- def name(MM, NN, VV="Lily"): pass name(NN='pp', MM='TT')
return語句:
return語句用來從一個函數返回即天出函數。我們也可以選擇從函數返回一個值。
函數一旦遇到return立刻終止函數的運行並返回其后的參數。
#!/usr/bin/env python # -*- coding:utf -8-*- def name(MM, VV="Lily"): if MM==VV: return MM else: return VV name('TT')
DocStrings:
奇妙的特性,文檔字符串。DocStrings是一個重要的工具,他可以幫助你的程序文檔更加簡單易懂,你應該盡量使用它。甚至可以在程序運行的時候從函數恢復文檔字符串!
#!/usr/bin/env python # -*- coding:utf -8-*- def printM_ax(x, y): '''Prints the m axim um of two num bers. The two values m ust be integers.''' x = int(x) # convert to integers, if possible y = int(y) if x > y: print(x, 'is m axim um ') else: print(y, 'is m axim um ') printM_ax(3, 5) print(printM_ax.__doc__) #執行結果 5 is m axim um Prints the m axim um of two num bers. The two values m ust be integers.
引用原文:
'''
~ 在函數的第一個邏輯行的字符串是這個函數的文檔字符串 。注意,DocStrings也適用於模塊和類,我們會在后面相應的章節學習它們。
~ 文檔字符串的慣例是一個多行字符串,它的首行以大寫字母開始,句號結尾。第二行是空行,從第三行開始是詳細的描述。 強烈建議,在你的函數中使用文檔字符串時遵循這個慣 例。
~ 你可以使用__doc__(注意雙下划線)調用printM_ax函數的文檔字符串屬性(屬於函數的名稱)。請記住Python把每一樣東西都作為對象,包括這個函數。我們會在后面的類一章學習更多關於對象的知識。
~ 如果你已經在Python中使用過help(),那么你已經看到過DocStings的使用了!它所做的只是抓取函數的__doc__屬性,然后整潔地展示給你。你可以對上面這個函數嘗試一下——只是在你的程序中包括help(printM_ax)。記住按q退出 help。
~ 自動化工具也可以以同樣的方式從你的程序中提取文檔。因此,我 強烈建議 你對你所寫的任何正式函數編寫文檔字符串。隨你的Python發行版附帶的pydoc命令,與help()類似地使用D ocStrings。
'''
九、模塊:
簡介
模塊就是一個包含了所有你定義的函數和變量的文件。為了在其他程序中重用模塊,模塊的文件名必須以.py為擴展名。
sys模塊的使用:(sys是system的縮寫)
示例:
#在Pycharm中運行
#filename:name.py
import sys print("The command line argum entsare:") for i in sys.argv: print(i) print("\n\nThe PYTHONPATH is", sys.path, "\n") #執行結果: The command line argum entsare: C:/Users/PycharmProjects/python(learning)/name.py The PYTHONPATH is ['C:\\Users\\PycharmProjects\\python(learning)', 'C:\\Users\\PycharmProjects\\python(learning)', 'C:\\Users\\Anaconda3\\python35.zip', 'C:\\Users\\Anaconda3\\DLLs', 'C:\\Users\\Anaconda3\\lib', 'C:\\Users\\Anaconda3', 'C:\\Users\\Anaconda3\\lib\\site-packages', 'C:\\Users\\Anaconda3\\lib\\site-packages\\Sphinx-1.4.1-py3.5.egg', 'C:\\Users\\Anaconda3\\lib\\site-packages\\win32', 'C:\\Users\\Anaconda3\\lib\\site-packages\\win32\\lib', 'C:\\Users\\Anaconda3\\lib\\site-packages\\Pythonwin', 'C:\\Users\\Anaconda3\\lib\\site-packages\\setuptools-23.0.0-py3.5.egg']
sys.argv變量是一個字符串的列表。sys.argv是包含了命令行參數的列表,即使用命令行傳遞給你的程序的參數。
(we are GG)跟在執行程序的后面作為參數傳遞給程序。python把把它存儲在sys.argv變量中。
sys.path所列內容為python執行時自動搜尋的所有路徑,如果被執行文件不再sys.path所列的路徑內,在執行時必須把文件所在路徑寫入,可看下例:
#在終端命令行運行
python C:/Users/PycharmProjects/python(learning)/name.py we are GG #執行結果: The command line argum entsare: C:/Users/PycharmProjects/python(learning)/name.py we are GG The PYTHONPATH is ['C:\\Users\\PycharmProjects\\python(learning)', 'C:\\Users\\PycharmProjects\\python(learning)', 'C:\\Users\\Anaconda3\\python35.zip', 'C:\\Users\\Anaconda3\\DLLs', 'C:\\Users\\Anaconda3\\lib', 'C:\\Users\\Anaconda3', 'C:\\Users\\Anaconda3\\lib\\site-packages', 'C:\\Users\\Anaconda3\\lib\\site-packages\\Sphinx-1.4.1-py3.5.egg', 'C:\\Users\\Anaconda3\\lib\\site-packages\\win32', 'C:\\Users\\Anaconda3\\lib\\site-packages\\win32\\lib', 'C:\\Users\\Anaconda3\\lib\\site-packages\\Pythonwin', 'C:\\Users\\Anaconda3\\lib\\site-packages\\setuptools-23.0.0-py3.5.egg']
首先,使用import語句導入sys模塊。
當python執行import sys語句的時候,它在sys.path變量中所列目錄中尋找sys.py模塊。找到后這個模塊的主塊中的語句將被執行,然后就可以使用模塊。注意,初始化過程僅在我們第一次輸入模塊的時候進行。
要注意的是,腳本的名稱總是sys.argv列表的第一個參數。所以,在這里,name.py是sys.argv[0]、we是sys.argv[1]......
.pyc文件
就是python為了加快模塊的導入而創建的字節編譯文件,這些文件就是以.pyc為擴展名。但你在下次從別的程序輸入這個模塊的時候,.pyc文件是十分有用的——它會快得多,因為一部分輸入模塊所需的處理已經完成。另外,這些字節編譯的文件於是與平台無關的。
from...import...語句
詳細內容:http://www.cnblogs.com/Guido-admirers/p/6085657.html
__name__模塊
每個模塊都有一個名稱,在模塊中可以通過語句找出模塊的名稱。這在一個場合特別的有用——當一個模塊沒第一次輸入的時候,這個模塊的主塊將被運行。假如我們只想在程序本身被使用時運行主塊,而在它被別的模塊輸入的時候不運行主塊,就要用到__name__屬性來完成。
示例:
#filename:name.py if __name__ == '__main__': print('This program is being run by itself') else: print('I an being imported from another module') #在命令行終端執行: $python name.py This program is being run by itself $python >>>import name I an being imported from another module >>>
在Python中每個模塊都有它的__name__,如果它是'__main__',這說明這個模塊被用戶單獨運行,我們可以進行相應的恰當操作。
dir函數
查看模塊的屬性生成一個屬性列表。
十、數據結構:
列表(list)
list是處理一組有序項目的數據結構,列表的創建(一個空列表)li=[]。列表是可變的數據類型,可以對列表進行添加、刪除或是搜索列表中的項目等的操作。
列表的操作方式與列表存在的方法:http://www.cnblogs.com/Guido-admirers/p/6124572.html
元祖(tuple)
元祖與列表相似,只是元祖是不可變的數據類型,所以列表有的方法元祖很多都沒有。
元祖的方法操作:http://www.cnblogs.com/Guido-admirers/p/6124616.html
含有0個或1個項目的元祖。一個空的元祖由一對空的圓括號組成,如tu=(),然而含單個元素的元祖必須在第一(唯一一個)項目后跟一個逗號,這樣python才能區分元祖和表達式中一個帶圓括號的對象,tp=(2,)是只包含2的一個元素的元祖。
元祖最常用的的用法是用在打印語句中:
age = 22 name = 'guido' print('%s is %d years old'%(name, age)) print('Why is %s playing with that python?'%name) #執行結果: guido is 22 years old Why is guido playing with that python?
字典(dict)
字典的組成是由鍵值對組成,鍵必須是唯一的,而且鍵只能使用不可變的對象(比如字符串),基本說,應該只使用簡單的對象作為鍵。
字典的使用及方法:http://www.cnblogs.com/Guido-admirers/p/6124623.html
序列
列表、元祖和字符串都是序列。序列的兩個主要特點是索引操作符和切片操作符。索引操作符讓我們可以從序列中抓取一個特定項目。切片操作符讓我們能夠獲取序列的一個切片,即一部分序列。
引用
當你創建一個對象並給它賦一個變量的時候。這個變量僅僅引用那個對象,而不是表示這個對象本身!也就是說變量名指向你計算機中存儲那個對象的內存。這被稱作名稱到對象的綁定。
示例(對象與引用):
print('Simple Assignment') shoplist = ['apple', 'mango', 'carrot', 'banana'] mylist = shoplist del shoplist[0] print('shoplist is',shoplist) print('mylist is',mylist) print("****************") print('Copy by making a full slice') mylist = shoplist[:] del mylist[0] print("****************") print('shoplist is', shoplist) print('mylist is', mylist) #執行結果: Simple Assignment shoplist is ['mango', 'carrot', 'banana'] mylist is ['mango', 'carrot', 'banana'] **************** Copy by making a full slice **************** shoplist is ['mango', 'carrot', 'banana'] mylist is ['carrot', 'banana']
注意:如果你想要復制一個列表或者類似的序列或者其他復雜的對象(不是如整數那樣簡單的對象),那么你必須使用切片操作符來取得拷貝。如果你只是想要使用另一個變量名,兩個名稱都引用同一個對象,那么如果你不小心的話,可能會引來各種麻煩。
解決問題——編寫一個Python腳本
問題:我想要一個可以為我的所有重要文件創建備份的程序。
問題分析:盡管這是一個簡單的問題,但是問題本身並沒有給我們足夠的信息來解決它。進一步的分析是必須的。例如,我們如何確定該備份哪些文件?備份保存在哪里?我們怎么樣存儲備份?
解決方法一:
首先聲明這個方法只是千百種方法中的一種,每個人設計的方法都不盡相同。
1、需要備份的文件和目錄由一個列表指定。
2、備份應該保存在主備份目錄中。
3、文件備份成一個zip文件。
4、zip存檔的名稱是當前的日期和時間。
5、我們使用標准的zip命令,它通常默認的隨linux發行版本提供。Windows用戶可以使用Info-Zip程序。注意的是你可以使用任何的存檔命令,只要他有命令行界面就可以了,那樣的話我們可以從我們的腳本中傳遞參數給它。
import os import time source = ['/home/swaroop/byte', '/home/swaroop/bin'] target_dir = "/mnt/e/backup/" target = target_dir+time.strftime('%Y %m %d %h %M %S')+'.zip' #利用time的strftime方法列出目前的時間 # print(target) zip_command = "zip -qr '%s' %s" % (target, ''.join(source)) #'%s'%s是為了給%s格式化的內容加引號,編輯字符串的格式。 # print(zip_command) if os.system(zip_command) == 0: #直接在shell命令下運行zip_command字符串所代表的命令 print("Successfulbackup to", target) else: print("Backup FAILED")
注釋:
time.strftime()括號內的內容%Y代表無世紀的年份,%m代表01—12的十進制月分數,其他依次類推。time模塊的更多方法http://www.cnblogs.com/Guido-admirers/p/6085657.html
zip命令有一些選項和參數。-q要用來表示zip命令安靜的工作。-r表示zip命令對目錄遞歸的工作,即它包含子目錄以及子目錄中的文件。兩個選項可以組合成縮寫-qr。選項后面跟着待創建的zip歸檔的名稱,然后再是待備份的文件和目錄列表。.join地方法把source列表轉換為字符串。
os.system函數就好像在系統中運行命令——運行成功,則返回0,否則它返回錯誤信號。
基於windows用戶:
可以把source列表和target目錄設置成任何文件和目錄名,但是要小心windows把反斜杠(\)作為目錄分隔符,而python用反斜杠表示轉義符! 所以要使用自然字符串(r"string")
上面的程序可以正確的工作,但是(通常)第一個程序並不是與你所期望的完全一樣。例如,可能有些問題你沒有設計恰當,又或者你在輸入代碼時發生了一點錯誤,等等。正常情況下,你應該回到設計環節或者調試程序。
解決方法二:
我們可以對它做一些優化以便讓它在我們的日常生活中變得更好。這稱為軟件的維護環節。
優化之一是采用更好的文件名機制——使用時間作為文件名,而當前的日期作為目錄名,存放在主目錄中。這樣做的一個優勢是你的備份會以等級結構存儲,跟容易管理。另一個優勢是文件名可以變短。還有一個優勢是采用各自獨立的文件夾可以幫助你方便的檢查是否每天創建了備份,因為只有創建了備份,才會出現那天的記錄。
import os import time source = ['/home/swaroop/byte', '/home/swaroop/bin'] target_dir = "/mnt/e/backup/" today = target_dir + time.strftime("%Y%m%d") now = time.strftime("%H %M %S") if not os.path.exists(today): #os.exists函數檢驗在主備份目錄中是否有以當前日期作為名稱的目錄 os.mkdir(today) print("Successfully created directory", today) target = today + os.sep + now + ".zip" #os.sep變量會根據你的操作系統給出目錄分隔符 # print(target) zip_command = "zip -qr '%s' %s" % (target, ''.join(source)) #'%s'%s是為了給%s格式化的內容加引號,編輯字符串的格式。 # print(zip_command) if os.system(zip_command) == 0: #直接在shell命令下運行zip_command字符串所代表的命令 print("Successfulbackup to", target) else: print("Backup FAILED")
os.sep:在Linux、Unix下它是'/',在windows下它是'\\',而在MacOS下它是':'。使用os.sep而非直接使用字符,會使我們的程序具有可移植性,可以在上述系統下工作。
解決方法三:
可以對每個歸檔名進行自定義輸入標記。
import os import time source = ['/home/swaroop/byte', '/home/swaroop/bin'] target_dir = "/mnt/e/backup/" today = target_dir + time.strftime("%Y%m%d") now = time.strftime("%H %M %S") comment = input("Enter a comment-->") if len(comment) == 0: #以用戶輸入的字符長度是否為0,來判斷用戶是否有輸入內容 target = today + os.sep + now + '.zip' else: target = today + os.sep + now + "_" + \ #同一邏輯行不同物理行,一定要加”\“反斜杠鏈接 comment.replace('', '_') + '.zip' #replace替換 if not os.path.exists(today): #os.exists函數檢驗在主備份目錄中是否有以當前日期作為名稱的目錄 os.mkdir(today) print("Successfully created directory", today) zip_command = "zip -qr '%s' %s" % (target, ''.join(source)) #'%s'%s是為了給%s格式化的內容加引號,編輯字符串的格式。 # print(zip_command) if os.system(zip_command) == 0: #直接在shell命令下運行zip_command字符串所代表的命令 print("Successfulbackup to", target) else: print("Backup FAILED")
最理想的創建方法是使用zipfile和tarfile,是python的標准庫。
軟件的開發過程:
1、什么(分析)
2、如何(設計)
3、編寫(實施)
4、測試(測試與調試)
5、使用(實施和開發)
6、維護(優化)
重要的:
我們創建這個備份腳本的過程是編寫程序的推薦方法——進行分析與設計。開始是實施一個簡單的版本。對它進行測試與調試。使用它以確信它如預期那樣的工作。再增加任何你想要的
特性,根據需要一次次的重復這個編寫—測試—使用的周期。記住軟件是長出來的,而不是建造的。