程序流程圖設計:
先給出開始和結束框圖,在中間按照順序設計加入大致的程序流程框圖,然后再進行完善和補充(增刪和修改)。
It may seem like a lot of work to sketch out a flow chart about the program first. After all, people want to play games, not look at flowcharts! But it is much easier to make changes and notice problems by thinking about how the program works before writing the code for it.
If you jump in to write the code first, you may discover problems that require you to change the code you’ve already written. Every time you change your code, you are taking a chance you create new bugs by changing too little or too much. It is much better to know what you want to build before you build it.
Import sys
Sys.path
Sys.path是一個目錄名稱的列表,它構成當前的搜索路徑。Sys內置模塊無法取得源代碼,它們是用C語言寫的。
可以通過sys.path.insert(0, new_path)插入一個新的目錄到sys.path列表的第一項。
這個很重要,因此剛開始我會重復幾次以防你忘記了:在 Python 里面所有東西都是對象。字符串是對象,列表是對象,函數是對象,類是對象,類的實例是對象,甚至模塊也是對象。
Python使用try...except塊處理異常,使用raise語句來拋出異常。
Os模塊提供了兩個函數處理當前目錄
import os
print(os.getcwd())
使用os.chdir()函數改變當前工作目錄
Os.path.join()函數從一個或者多個路徑片段中構造一個路徑名
Os.path.expanduser()用來將包含~符號的路徑擴展為完整的路徑。
Os.path.split()可以用于分割完整路徑名,目錄名和文件名
(shortname, extension) = os.path.splitext(filename) 可以對文件名和拓展名進行分割
glob 模塊是 Python 標準庫中的另一個工具,它可以通過編程的方法獲得一個目錄的內容,并且它使用熟悉的命令行下的通配符。 glob 模塊使用 shell 風格的通配符。
獲取文件元信息
每一個現代文件系統都對文件存儲了元信息: 創建時間,最后修改時間,文件大小等等。Python 單獨提供了一個的 API 用于訪問這些元信息。 你不需要打開文件。知道文件名就足夠了。
當前工作目錄是 examples 文件夾。
feed.xml 是 examples 文件夾中的一個文件。 調用 os.stat() 函數返回一個包含多種文件元信息的對象。
st_mtime 是最后修改時間,它的格式不是很有用。(技術上講,它是從紀元,也就是 1970 年 1 月 1 號的第一秒鐘,到現在的秒數)
time 模塊是 Python 標準庫的一部分。 它包含用于在不同時間格式中轉換,將時間格式化成字符串以及處理時區的函數。
time.localtime() 函數將從紀元到現在的秒數這個格式表示的時間(os.stat()函數返回值的 st_mtime 屬性)轉換成更有用的包含年、月、日、小時、分鐘、秒的結構體。這個文件的最后修改時間是 2009 年 7 月 13 日下午 5:25。
操作實例(使用之前的humansize.py進行查看):
os.getcwd()
'/home/wsx/python_learn/Dive_into_python'
metadata = os.stat('humansize.py')
metadata.st_mtime
1484925139.3738046
import time
time.localtime(metadata.st_mtime)
time.struct_time(tm_year=2017, tm_mon=1, tm_mday=20, tm_hour=23, tm_min=12, tm_sec=19, tm_wday=4, tm_yday=20, tm_isdst=0)
metadata.st_size
702
import humansize
humansize.approximate_size(metadata.st_size)
'0.7 KiB'
構造絕對路徑
在前一節中,glob.glob() 函數返回一個相對路徑的列表。第一個例子的路徑類似'examples\feed.xml',而第二個例子的路徑'romantest1.py'更短。只要你保持在當前工作目錄中,你就可以使用這些相對路徑來打開文件或者獲得文件的元信息。但是當你希望構造一個從根目錄開始或者是包含盤符的絕對路徑時,你就需要用到os.path.realpath()函數了。
列表解析創造一個新的列表而不改變原列表。
可以安全的將列表解析的結果賦值給被映射的變量。Python會在內存中構造新的列表,在列表解析完成后將結果賦值給原來的變量。
你可以在列表解析中使用任何的 Python 表達式, 包括 os 模塊中用于操作文件和目錄的函數。
你可以在列表解析的最后加入 if 子句來過濾列表。對于列表中每一個元素 if 關鍵字后面的表達式都會被計算。如果表達式的計算結果為 True,那么這個元素將會被包含在輸出中。這個列表解析在當前目錄查找所有.py 文件,而 if 表達式通過測試文件大小是否大于 6000 字節對列表進行過濾。有 6 個符合條件的文件,所以這個列表解析返回包含六個文件名的列表。
到目前為止的例子中的列表解析都只是用了一些簡單的表達式, 乘以一個常數、調用一個函數或者是在過濾后返回原始元素。 然而列表解析并不限制表達式的復雜程度。
交換字典的鍵和值
這里是一個可能有用的通過字典解析實現的小技巧:鍵和值。
a_dict = {'a': 1, 'b': 2, 'c': 3}
{value:key for key, value in a_dict.items()}
{1: 'a', 2: 'b', 3: 'c'}
UNICODE
有一種 Unicode 編碼方式每 1 個字符使用 4 個字節。它叫做UTF‐82,因為 32 位 = 4 字節。UTF‐32 是一種直觀的編碼方式;它收錄每一個 Unicode 字符(4 字節數字)然后就以那個數字代表該字符。這種方法有其優點,最重要的一點就是可以在常數時間內定位字符串里的第 N 個字符,因為第 N 個字符從第4×Nth 個字節開始。另外,它也有其缺點,最明顯的就是它使用 4 個“詭異”的字節來存儲每個“詭異”的字符...
盡管有Unicode字符非常多,但是實際上大多數人不會用到超過前 65535 個以外的字符。因此,就有了另外一種Unicode編碼方式,叫做UTF‐16(因為 16 位 = 2 字節)。UTF‐16 將 0–65535 范圍內的字符編碼成 2 個字節,如果真的需要表達那些很少使用的“星芒層(astral plane)”內超過這 65535 范圍的Unicode字符,則需要使用一些詭異的技巧來實現。UTF‐16 編碼最明顯的優點是它在空間效率上比UTF‐32 高兩倍,因為每個字符只需要 2 個字節來存儲(除去 65535 范圍以外的),而不是UTF‐32 中的 4 個字節。并且,如果我們假設某個字符串不包含任何星芒層中的字符,那么我們依然可以在常數時間內找到其中的第N個字符,直到它不成立為止這總是一個不錯的推斷...
但是對于 UTF‐32 和 UTF‐16 編碼方式還有一些其他不明顯的缺點。不同的計算機系統會以不同的順序保存字節。這意味著字符 U+4E2D 在 UTF‐16 編碼方式下可能被保存為 4E 2D 或者 2D 4E,這取決于該系統使用的是大尾端(big‐endian)還是小尾端(little‐endian)。(對于 UTF‐32 編碼方式,則有更多種可能的字節排列。)只要文檔沒有離開你的計算機,它還是安全的 — 同一臺電腦上的不同程序使用相同的字節順序(byte order)。但是當我們需要在系統之間傳輸這個文檔的時候,也許在萬維網中,我們就需要一種方法來指示當前我們的字節是怎樣存儲的。不然的話,接收文檔的計算機就無法知道這兩個字節 4E 2D 表達的到底是 U+4E2D 還是 U+2D4E。
為了解決這個問題,多字節的Unicode編碼方式定義了一個“字節順序標記(Byte Order Mark)”,它是一個特殊的非打印字符,你可以把它包含在文檔的開頭來指示你所使用的字節順序。對于UTF‐16,字節順序標記是U+FEFF。如果收到一個以字節FF FE開頭的UTF‐16 編碼的文檔,你就能確定它的字節順序是單向的(one way)的了;如果它以FE FF開頭,則可以確定字節順序反向了。
不過,UTF‐16 還不夠完美,特別是要處理許多 ASCII 字符時。如果仔細想想的話,甚至一個中文網頁也會包含許多的 ASCII字符 — 所有包圍在可打印中文字符周圍的元素(element)和屬性(attribute)。能夠在常數時間內找到第 Nth 個字符當然非常好,但是依然存在著糾纏不休的星芒層字符的問題,這意味著你不能保證每個字符都是 2 個字節長,所以,除非你維護著另外一個索引,不然就不能真正意義上的在常數時間內定位第 N 個字符。另外,朋友,世界上肯定還存在很多的 ASCII 文本... 另外一些人琢磨著這些問題,他們找到了一種解決方法: UTF-8
格式說明符
但是,還有一些問題我們沒有講到!再來看一看 humansize.py中那一行奇怪的代碼:
if size < multiple:
return '{0:.1f} {1}'.format(size, suffix)
{1}會被傳遞給 format()方法的第二個參數替換,即 suffix。但是{0:.1f}是什么意思呢?它其實包含了兩方面的內容:{0}你已經能理解,:.1f 則不一定了。第二部分(包括冒號及其后邊的部分)即格式說明符(format specifier),它進一步定義了被替換的變量應該如何被格式化。
?格式說明符的允許你使用各種各種實用的方法來修飾被替換的文本,就像 C 語言中的 printf()函數一樣。我們可以添加使用零填充(zero‐padding),襯距(space‐padding),對齊字符串(align strings),控制 10 進制數輸出精度,甚至將數字轉換成 16 進制數輸出。 在替換域中,冒號(:)標示格式說明符的開始。“.1”的意思是四舍五入到保留一們小數點。“f”的意思是定點數(與指數標記法或者其他 10 進制數表示方法相對應)。因此,如果給定size 為 698.24,suffix 為'GB',那么格式化后的字符串將是'698.2 GB',因為 698.24 被四舍五入到一位小數表示,然后后綴'GB'再被追加到這個串最后。
'{0:.1f} {1}'.format(698.24, 'GB')
'698.2 GB'
其他字符串常用方法
我們可以在 Python 的交互式 shell 里輸入多行(multiline)字符串。一旦我們以三個引號標記多行字符串的開始,按 ENTER 鍵,Python shell 會提示你繼續這個字符串
的輸入。連續輸入三個結束引號以終止該字符串的輸入,再敲ENTER 鍵則會執行該條命令(在當前例子中,把這個字符串賦給變量 s)。
splitlines()方法以多行字符串作為輸入,返回一個由字符串組成的列表,列表的元素即原來的單行字符串。請注意,每行行末的回車符沒有被包括進去。
lower()方法把整個字符串轉換成小寫的。(類似地,upper()方法執行大寫化轉換操作。)
count()方法對串中的指定的子串進行計數。是的,在那一句中確實出現了 6 個字母“f”。
Byte
使用“byte 字面值”語法 b''來定義 bytes 對象。byte 字面值里的每個字節可以是 ASCII 字符或者是從\x00 到\xff 編碼了的 16 進制數。
bytes 對象的類型是 bytes。
跟列表和字符串一樣,我們可以通過內置函數 len()來獲得bytes 對象的長度。
使用+操作符可以連接 bytes 對象。操作的結果是一個新的bytes 對象。
連接 5 個字節的和 1 個字節的 bytes 對象會返回一個 6 字節的 bytes 對象。
一如列表和字符串,可以使用下標記號來獲取 bytes 對象中的單個字節。對字符串做這種操作獲得的元素仍為字符串,而對 bytes 對象做這種操作的返回值則為整數。確切地說,是 0–255 之間的整數。
bytes對象是不可變的;我們不可以給單個字節賦上新值。如果需要改變某個字節,可以組合使用字符串的切片和連接操作(效果跟字符串是一樣的),或者我們也可以將bytes對象轉換為bytearray對象。
Python源碼的編碼方式
Python 3 會假定我們的源碼 — 即.py 文件 — 使用的是 UTF‐8 編碼方式。
?Python 2 里,.py文件默認的編碼方式為ASCII。Python 3 的源碼的默認編碼方式為UTF‐8 如果想使用一種不同的編碼方式來保存 Python 代碼,我們可
以在每個文件的第一行放置編碼聲明(encoding declaration)。以下聲明定義.py 文件使用 windows‐1252 編碼方式:
‐‐ coding: windows‐1252 ‐‐
從技術上說,字符編碼的重載聲明也可以放在第二行,如果第一行被類UNIX系統中的hash‐bang命令占用了。
!/usr/bin/python3
‐‐ coding: windows‐1252 ‐‐
為什么要用正則表達式
所有的現代編程語言都有內建字符串處理函數。在 python 里查找,替換字符串的方法是:index()、 find()、split()、 count()、 replace()等。但這些方法都只是最簡單的字符串處理。比如:用index()方法查找單個子字符串,而且查找總是區分大小寫的。為了使用不區分大小寫的查找,可以使用 s.lower()或者s.upper(),但要確認你查找的字符串的大小寫是匹配的。replace() 和 split() 方法有相同的限制。
如果使用 string 的方法就可以達到你的目的,那么你就使用它們。它們速度快又簡單,并且很容易閱讀。但是如果你發現自己要使用大量的 if 語句,以及很多字符串函數來處理一些特
例,或者說你需要組合調用 split() 和 join() 來切片、合并你的字符串,你就應該使用正則表達式。
正則表達式有強大并且標準化的方法來處理字符串查找、替換以及用復雜模式來解析文本。正則表達式的語法比我們的程序代碼更緊湊,格式更嚴格,比用組合調用字符串處理函數的方法更具有可讀性。甚至你可以在正則表達式中嵌入注釋信息,這樣就可以使它有自文檔化的功能。
?如果你在其他語言中使用過正則表達式(比如perl,javascript 或者 php),python 的正則表達式語法和它們的很像。閱讀 re 模塊的摘要信息可以了解到一些處理函數以及它們參數的一些概況。 ?
^ 匹配字符串開始. $ 匹配字符串結尾
為了在正則表達式中表達這個獨立的詞,你可以使用‘\b’。它的意思是“在右邊必須有一個分隔符”。在 python 中,比較復雜的是‘\’字符必須被轉義,這有的時候會導致‘\’字符傳染(想想可能還要對\字符做轉義的情況)。這也是為什么 perl 中的正則表達式比 python 的簡單的原因之一。另一方面,perl 會在正則表達式中混合其他非正則表達式的語法,如果出現了 bug,那么很難區分這個bug 是在正則表達式中,還是在其他的語法部分。
為了解決‘\’字符傳染的問題,可以使用原始字符串。這只需要在字符串的前面添加一個字符‘r’。它告訴 python,字符串中沒有任何字符需要轉義。‘\t’是一個制表符,但 r‘\t’只是一個字符‘\’緊跟著一個字符 t。我建議在處理正則表達式的時候總是使用原始字符串。否則,會因為理解正則表達式而消耗大量時間(本身正則表達式就已經夠讓人困惑的了)。
正則表達式的匹配規則和使用范圍,使用時需要找手冊多使用熟練。
?
^ 匹配字符串開始位置。
$ 匹配字符串結束位置。
\b 匹配一個單詞邊界。
\d 匹配一個數字。
\D 匹配一個任意的非數字字符。
x? 匹配可選的 x 字符。換句話說,就是 0 個或者 1 個 x 字
符。
x* 匹配 0 個或更多的 x。
x+ 匹配 1 個或者更多 x。
x{n,m} 匹配 n 到 m 個 x,至少 n 個,不能超過 m 個。
(a|b|c) 匹配單獨的任意一個 a 或者 b 或者 c。
(x) 這是一個組,它會記憶它匹配到的字符串。你可以用re.search 返回的匹配對象的 groups()函數來獲取到匹配的值。
正則表達式非常強大,但它也并不是解決每一個問題的正確答案。你需要更多的了解來判斷哪些情況適合使用正則表達式。
某些時候它可以解決你的問題,某些時候它可能帶來更多的問題。
兩個松散正則表達式實例
pattern = '''
... ^ # beginning of string
... M{0,3} # thousands - 0 to 3 Ms
... (CM|CD|D?C{0,3}) # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 Cs),
... # or 500 - 800 (D, followed by 0 to 3Cs)
... (XC|XL|L?X{0,3}) # tens - 90 (XC), 40(XL), 0-30 (0 to 3 Xs),
... # or 50 - 80 (L, followed by 0 to 3 Xs)
... (IX|IV|V?I{0,3}) # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 Is),
... # or 5-8 (V, followed by 0 to 3 Is)
... $ # end of string
...
... '''
re.search(pattern, 'M', re.VERBOSE)
phonePattern = re.compile(r'''
... # don't match begining of string number can start anywhere
... (\d{3}) # area code is 3 digits (e.g. '800')
... \D* # optional separator is any number of non-digits
... (\d{3}) # trunk is 3 digits
... \D* # optional separator
... (\d{4}) # rest of number is 4 digits
... \D* # optional separator
... (\d*) # extension is optional and can be any number of digits
... $ # end of strinh
... ''', re.VERBOSE)
phonePattern.search('work 1-(800) 555.1212 #1234').groups()
('800', '555', '1212', '1234')
16.Pickling allows us to store and fetch native Python objects as they are and in a single step--the pickle module is remarkably easy to use.
from initdata import db
import pickle
dbfile = open('people-pickle', 'wb')
pickle.dump(db, dbfile)
dbfile.close()
import pickle
dbfile = open('people-pickle', 'rb')
db = pickle.load(dbfile)
for key in db:
print(key, '=>\n', db[key])
print(db['sue']['name'])
17.Pickling objects to files is an optimal scheme in many applications. If we really want keyed access to records, the Python standard library offers an even higher-level tool: shelves.
18.If you’ve already studied Python in any sort of depth, you probably already know that this is where its OPP support begins to become attractive:
Structure-
With OPP, we can naturally associate processing logic with record data-classes provide both a program unit that combines logic and data in a single package and a hierarchy that allows code to be easily factored to avoid redundancy.
Encapsulation-
With OPP, we can also wrap up details such as name processing and pay increases behind method functions-i.e., we are free to change method implementations without breaking their users.
Customization-
And with OPP, we have a natural growth path. Classes can be extended and customized by coding new subclasses, without changing or breaking already working code.
19.If we plan to distribute this GUI widely, we might package it up as a standalone executable program - a frozen binary in Python terminology - using third-party tools such as Py2Exe, PyInstaller, and others (search the Web for pointers).
If you need to do graphics beyond basic windows, the tkinter Canvas widget supports freeform graphics. Third party extensions such as Blender, OpenGL, VPython, VTK, Maya, and PyGame provide even more advanced graphics, visualization, and animation tools for use with Python scripts. Moreover, the PMW, Tix, and ttk widget kits mentioned earlier extend tkinter itself.
For more advanced applications, a wealth of toolkits and frameworks for Python - including Django, TurboGears, Google's App Engine, pylons, web2py, Zope, Plone, Twisted, CherryPy, Webware, mod_python, PSP, and Quixote-can simplify common tasks and provide tools that we might otherwise need to code from scratch in the CGI world. add Flex, Silverlight, and pyjamas
這些記錄略顯雜亂,以后我會根據自己的學習情況,有序地整理出其中的精要部分。