做者:taowen, billrice
Lesson 1
準備好學習Python的環境
運行環境能夠是linux或者是windows: 一、linux redhat的linux安裝上去以後必定會有python的(必須的組件),在命令行中輸入python回車。這樣就能夠進入一個 >>>的提示符 二、windows 安裝好了python以後,在開始菜單裏面找到Python2.3->IDLE,運行也會進入一個有 >>>提示符的窗口
開始嘗試Python 一、輸入: welcome = "Hello!" 回車 而後又回到了>>> 二、輸入: print welcome 回車 而後就能夠看到你本身輸入的問候了。
Lesson 2
搞定環境以後的前行 Python有一個交互式的命令行,你們已經看到了吧。因此能夠比較方便的學習和嘗試,不用「新建-存檔-編譯-調試」,很是適合快速的嘗試。
一開始從變量開始(其實說變量,更準確的是對象,Python中什麼均可以理解爲對象)。
變量 welcome = "hello!" welcome就是變量名,字符串就是變量的類型,hello!就是變量的內容,""表示這個變量是字符串,""中間的是字符串的內容。 熟悉其餘語言的人,特別是編譯類型的語言,以爲沒有變量的聲明很奇怪。在python中用賦值來表示我要這麼一個變量,即便你不知道要放什麼內容,只是要先弄一個地方來放你的東西,也要這麼寫: store = "" 不過這個仍是說明了store是字符串,由於""的緣故。
have a try
代碼: |
[複製到剪貼板] |
tmp_storage = "" welcome = "hello!" tmp_storage = welcome print tmp_storage |
|
你會發現一樣的問候出現了。
字符串 字符串是用""標記的,可是用''也能夠(不要說你看不出一個是雙引號,一個是單引號),二者之間是有一丁點區別,不過你能夠不用理會。實際上是差很少的。字符串有不少本身的操做,最經常使用的是這樣的:
代碼: |
[複製到剪貼板] |
welcome = "hello" you = "world!" print welcome+you |
|
運行以後就會發現她輸出了helloworld!。
更多變量 變量還有幾種類型。 數 字符串 列表 字典 文件 勿庸置疑,這些都是很是很是經常使用的。對於數字就不用講了那就是:
代碼: |
[複製到剪貼板] |
radius = 10 pi = 3.14 area = pi*radius**2 print "the area is", area |
|
下次講列表和字典
Lesson 3
Python中的數學結構 數學中你學什麼東西最多遍?我想根據個人一點淺薄經驗(
雖然我是數學系的),學得最多的是集合,不管什麼數學書都從集合開始講起。而後講函數呢,又必然把映射再講一遍。能夠說,集合和映射是數學中最基本的結構了。
Python對於數據結構很是明智的內置了兩個,回想我寫C的程序,每每是一開始就是用struct拼一個鏈表出來(
重複勞動)。Python中提供了列表(list)和字典(dict)兩種數據結構。他們分別對應的原型是集合和映射。這個你應該明白了,只是表示方法有一點不同而已。
列表 列表的英文名是list嘛,因此我取一個名字叫
代碼: |
[複製到剪貼板] |
my_list = [] 這個就產生了一個空的列表。而後給它賦值 my_list = [1,2] print my_list my_list.append(3) print my_list |
|
很是容易明白的。append前面加了一個點,這個表示append是my_list方法。我實在不想又去給你解釋什麼是對象,什麼是成員方法,而後扯出一大段出來。 list是能夠索引的: print my_list[1] 不過你或許會不明白爲何是2,而不是顯示的是1。由於索引從0開始,要輸出第一個元素: print my_list[0]
字典
這個產生了一個空字典,contact。而後往裏面填充內容:
代碼: |
[複製到剪貼板] |
contact={} contact["name"]="taowen" contact["phone"]=68942443 |
|
name就是你查字典的時候要查找的單詞,taowen就是查到的內容。不過你如今不是查,而是在寫這個字典。同理添加了phone這個詞條。 如今添加好了,看看contact的內容,怎麼查看?本身想辦法吧。。。 若是你悟性夠,就會發現python不少操做是通用的,既然可以print 1, print "", print my_list,那麼其餘數據類型的變量就沒有理由不能用了。
結合列表和字典
代碼: |
[複製到剪貼板] |
contact_list=[] contact1={} contact1['name']='taowen' contact1['phone']=68942443 contact_list.append(contact1) contact2={} contact2['name']='god' contact2['phone']=44448888 contact_list.append(contact2) |
|
呵呵,夠複雜的吧。你能夠想出我爲何要用兩個contact字典呢?。。。
Lesson 4
用不一樣的方式來操做Python 到如今爲止,咱們用的都是交互式的命令行來操做的,的倒是很方便,是吧?不過,複雜一些的狀況就不那麼好使了,來換一種方式來操做Python
在IDLE中點擊File->New Window,出現一個新窗口(對於linux下,你要用vim或者emacs或者pico把文本的源文件寫好了)。爲了方便,先點擊File->Save,填入my_try.py。這樣可以讓編輯器知道在編輯python的源文件,會把你輸入的代碼進行一點上色的處理。
填入下面的代碼:
代碼: |
[複製到剪貼板] |
i = 5 n = 0 while i>0: n = n + i i = i - 1 print n |
|
你會發現輸入:以後,自動會給縮進。並且也沒有在python中發現和C/C++中相似的{}標記也沒有pascal中的begin end;,其實縮進就是python中表示一段代碼的從屬關係的標記方法。表示n=n+1和i=i-1這兩句都是while的。程序的運行邏輯應該不用解釋了吧。就是運行5+4+3+2+1的結果。
運行代碼 按F5,可能提示你沒有存盤,照着辦就是了。 發揮你的能力,計算從1到10的全部偶數的和(提示,可能沒有你想象的那麼智能)。
Lesson 5
Python中的輸入與判斷 健全的程序大凡都須要輸入的功能,因此要學習一下簡單的輸入: 輸入要使用的是raw_input或者input函數,區別是raw_input直接把你的輸入做爲字符串返回,而input則在raw_input的基礎上把字符串轉換爲數字返回(若是你輸入$@#$$怎麼辦?本身試試看)。咱們就利用這兩個輸入函數來做一些有趣的事情。
代碼: |
[複製到剪貼板] |
your_name = raw_input("please input your name:") hint = "welcome! %s" % your_name print hint |
|
不簡單吧,還有%呢。%s表示在這個位置插入一個字符串,%表示把後面提供的參數「推」入前面的字符串中,因此推的結果是把%s推出去了,把your_name給填入那個地方了。printf知道吧,C中的printf就是同樣的嘛。
代碼: |
[複製到剪貼板] |
inputed_num = 0 while 1: inputed_num = input("input a number between 1 and 10\n") if inputed_num >= 10: pass elif inputed_num < 1: pass else: break print "hehe, don't follow, won't out" |
|
pass就是pass了,過了嘛,什麼都不幹了。break就是跳出這個while 1(無窮循環,1老是真的,while老是執行)。\n是換行,不會所有忘光了吧。
Lesson 6
Python餘興節目
代碼: |
[複製到剪貼板] |
from Tkinter import * root = Tk() w = Label(root, text="Hello, world!") w.pack() root.mainloop() |
|
呵呵,一次太超前了一點,不過也不是解釋不清楚。我乾脆也不解釋了吧。給你們增進一點興趣。
--------- 仍是解釋一下 fromt Tkinter import * 是引入一個模塊,這個模塊用來建立GUI(Graphic User Interface)窗口 Tk()建立了一個主窗口 Label()建立一個標籤 Label的第一個參數是root代表Label是在這個主窗口中的。 w.pack()是指用缺省的方式把Label放置在主窗口中 root.mainloop()開始了一個循環,是等待你的輸入的循環。
Lesson 7
Python基本語法要素齊動員 如今的目的是儘可能想出一個用的東西僅限於內置的變量類型和語句的一個綜合的例子,我想仍是那個聯繫人表的例子吧
代碼: |
[複製到剪貼板] |
################ #呵呵,還忘記了講註釋 #第一個算是完整的程序 ################ contact = {} contact_list = [] while 1: contact['name'] = raw_input("please input name: ") contact['phone'] = raw_input("please input phone number: ") contact_list.append(contact.copy()) go_on = raw_input("continue?\n") if go_on == "yes": pass elif go_on == "no": break else: print "you didn't say no\n" i = 1 for contact in contact_list: print "%d: name=%s" % (i, contact['name']) print "%d: phone=%s" % (i, contact['phone']) i = i + 1 |
|
首先是回憶一下字符串 字符串既可以用""也可以用''。而後是頗有特點的%操做,起到格式化字符串的做用,前面僅僅在字符串中有一個%s,如今有%d和%s兩個,分別表明插入十進制數值和字符串於%x標記的位置處。
而後是列表 列表是順序的序列,用append在後面附加,也能構用索引值索引。因此咱們徹底能夠用一個變量保存len(contact_list)獲得的長度,而後一個個的遍歷,不過這裏展現了另一種很是方便的方法。並且值得注意的是append()中的參數,我使用了contact.copy(),你能夠嘗試着把copy()給去掉,觀察結果你就知道了所謂的append是怎麼幹的了,特別是你對指針之類的東西頗有感受的話(可是在Python中是沒有指針這個概念的)
再來看看字典 字典是鍵(key)和值(value)的對應組合成的無序的序列。因此你存的時候要指明鍵(name或者phone),並且取的時候也是同樣的。
接下來是判斷 if是很好用的,==表示判斷兩個是否相等,=表示把右邊的賦給左邊的。並且能夠直接判斷字符串是否相等,這個太方便了,若是你曾經用過strcpy()的話,就知道了。elif是表示else if的意思,若是if不知足就判斷elif的條件是否知足,最後是到else中去。
循環是個主體 while和for都是循環。不過這裏while就沒什麼說的了,又是很經典的while 1,死循環,而後必須在裏面用break來跳出。for和C中的for是不同的,for in纔是一個完整的語句,指的是從一個可以逐一取值的序列中(好比list),一個一個的取出值賦給for後面指定的變量中,直到取空,循環結束。其實回想通常用C中的for的經歷,也大致如此。並且你還能夠用for i in range(1,100)來指定一個範圍從多少到多少。能夠說for in充分體現了python的體貼周到,用起來很直觀,不會繞彎。
接下來就是運行了,你們慢慢調試吧。下次多是講異常處理,由於我以爲在深刻到使用各類高級的要素以前,先要學會怎麼去處理異常。最多見的異常應該是input(),而後你給出的輸入是一個沒法轉換爲數字的字符串了,那麼咱們就要來處理它。
Lesson 8
Python中的錯誤檢測 寫程序什麼最重要?完成功能最重要。可是程序中不免要有用戶的輸入,對於這些寫的時候未可預知的因素中間可能出現的錯誤,通常稱做異常。對於異常狀況的處理,不一樣語言有不一樣的作法,好比檢查函數的返回值之類的,可是那種辦法會把代碼弄成一團漿糊。Python在這個方面是比較先進的,咱們從一個例子來看看:
呵呵,看不一樣吧。其實input是輸入,print是輸出。也就是把輸入的東西當即輸出。可是這個和
有什麼不一樣呢? 不一樣的地方是,input()會在raw_input()接收了「
字符串」的輸入以後進行一些處理,好比你是輸入1+2,而後輸出的就是3了,而raw_input就是原本來本的1+2的輸出了。用代碼表示就是
eval是求表達式的值,任何一個簡單的python表達式,就像1+2這樣的做爲字符串送入,就能把值從eval處理以後取出來。 如今你實驗一下"sdfsdf」以後,你會發現提示你
引用: |
Traceback (most recent call last): File "<pyshell#4>", line 1, in -toplevel- input() File "<string>", line 0, in -toplevel- NameError: name 'sdfsdf' is not defined |
|
若是輸入其餘稀奇古怪的字符串還可能有其餘的出錯提示,咱們如今要作的就是捕捉這種由用戶輸入引發的錯誤。這麼來做:
代碼: |
[複製到剪貼板] |
try: print input() except: print 'there is an error in your input' |
|
這下你不管怎麼輸入都不會有什麼其餘的提示了,就是本身設定的print語句做爲提示。如今把try except的組合去掉,回到print input()你再嘗試一下: 1/0 這個顯然是一個錯誤,被零除的錯誤。那麼專門來捕捉一下這個錯誤:
代碼: |
[複製到剪貼板] |
try: print input() except ZeroDivisionError: print 'can not be divided by zero' |
|
這下你可以捕捉到被零除的錯誤了。而後你再嘗試其餘的輸入,可能錯誤就沒有被捕捉了。因此再補上:
代碼: |
[複製到剪貼板] |
try: print input() except ZeroDivisionError: print 'can not be divided by zero' except: print 'there is an error in your input' |
|
注意,捕捉全部錯誤的except必須放在全部的except的最後一位。明白了?OK
還有更多的可以捕捉的錯誤,本身查手冊吧(暫時看不了手冊不要緊,慢慢來嘛)。之後還可以本身raise(引起)異常呢。不過那都是比較高級的應用了,對於出錯處理從一開始就有這個印象,並牢記在心中對於之後寫大一些的軟件頗有好處。
Lesson 9
走向模塊化的第一步 大規模的程序設計須要你把一個大的程序拆分紅n個模塊。而後把模塊進行組合,交互成爲一個完整的程序。你不可能像如今這樣,從頂寫到尾。。。 那麼咱們從
函數開始。
代碼: |
[複製到剪貼板] |
def square(x): return x**2 print square(5) |
|
簡單吧,這個是我看過的函數定義中最簡潔的。def表示這個開始定義一個函數,x是參數,參數是不須要類型的,由於python是不須要明確指出類型的。return是返回值,返回的值插入到調用函數的地方。再複雜一些
代碼: |
[複製到剪貼板] |
def multiply(a, b): return a*b print multiply(1,2) |
|
這是兩個參數的函數。那麼返回兩個值呢?
代碼: |
[複製到剪貼板] |
def swap(a, b): return (b,a) print swap(1,2) |
|
呵呵,其實這裏返回的並非兩個值,而是一個值。怎麼說呢。(b, a)就是一個東西,是一個元組(turple),你能夠用這樣的方式成生一個元組,並使用它。元組是基本的變量類型:
代碼: |
[複製到剪貼板] |
my_turple = (1, 2, 3) my_list = [] for i in my_turple: my_list.append(i) print my_list |
|
其實元組和列表很是像,可是列表的長度是能夠變化的,並且成員是能夠改變的。可是元組是什麼都不能變的,是隻讀的。
對於高級一點的話題:傳遞進來的參數是否能夠被修改,這個問題取決於你傳遞了什麼近來。若是是數字或者字符串,是不可以改變的,可是若是是這樣的:
代碼: |
[複製到剪貼板] |
def test_func(list_be_passed): list_be_passed[0] = 'towin' my_list = ['taowen'] print my_list test_func(my_list) print my_list |
|
就可以改變傳遞近來的參數了,因此處理的時候要當心,必要的時候copy一下再傳遞。
函數簡單吧,可是很好用的。想起C中的函數那麼那麼多麻煩,真是感慨萬千啊。下面是應該講GUI編程呢,仍是面向對象呢?思考一下
Lesson 10
Python的文件操做 文件操做....是一個語言和外界聯繫的主要方法....如今以txt爲例簡單的講一下...
首先是創建關聯...假設在存在如下文件 c:\a.txt
代碼: |
[複製到剪貼板] |
This is line #1 This is line #2 This is line #3 END |
|
代碼: |
[複製到剪貼板] |
>>> xxx = file('c:\\a.txt', 'r') |
|
關鍵字的第一部分,是文件路徑及名稱。注意這裏面,路徑須要用
\\ 第二部分,是對文件的模式或者叫權限,通常有如下3種 "r" (read), "w" (write)和 "a"(append).
以後,就能夠利用 xxx_content = infile.read() xxx_content = infile.readlines() 來讀取文件內容了
代碼: |
[複製到剪貼板] |
>>> xxx = file('c:\\a.txt', 'r') >>> xxx_content = xxx.read() >>> print xxx_content This is line #1 This is line #2 This is line #3 END >>> xxx.close() >>>
>>> infile = file('c:\\a.txt', 'r') >>> xxx = file('c:\\a.txt', 'r') >>> for xxx_line in xxx.readlines(): print 'Line:', xxx_line Line: This is line #1 Line: This is line #2 Line: This is line #3 Line: END >>> xxx.close() >>> |
|
而後是文件的寫入
代碼: |
[複製到剪貼板] |
>>> xxx=file('c:\\test.txt','w') >>> xxx.write('billrice') >>> xxx.write('testtest') >>> xxx.write('enter\n') >>> xxx.writelines(['billrice','ricerice']) >>> xxx.close() >>> >>> xxx=file('c:\\test.txt','r') >>> content=xxx.read() >>> print content billricetesttestenter billricericerice >>> |
|
須要注意的是...在
xxx.close()以前,c盤下面只有一個空空的test.txt,xxx.close()的做用至關於最後的存盤。
Lesson 11
走向模塊化的第二步 函數上面還能是什麼呢?內嵌函數^_^,其實python是支持的。不過用起來會讓你吐血的,LGB名稱查找規則。。。(寒)。python是面向對象的,對於面向對象的支持挺好玩的。
代碼: |
[複製到剪貼板] |
class person: def __init__(self): self.name = 'taowen' self.id = 20022479 def say_id(self): print "%s's id is %d" % (self.name, self.id) me = person() me.say_id() |
|
比較複雜了吧。若是不熟悉面向對象的概念的,可能會以爲暈。我來解釋一下。所謂面向對象是把數據和操做數據的函數放到同一個類中去,而後用類來建立對象,操做的時候可以比較方便(很不精確的說法,任何一個OO高手均可以把我罵得屁都不是
)。
類 類是class關鍵來定義的。class person:就是說定義一個類,名字叫person。
對象 對象是用類來產生的。因此me就是對象,產生的辦法就是像調用函數同樣,person(),並且()中是可以放參數的,何時要參數,看下面的「初始化函數「
初始化函數 類能夠有本身的初始化函數,每次類被建立的時候(調用person()這樣的語句的時候),都會調用它。這個在C++中的名稱是構造函數。__init__是必須的名字,你不能用其餘名字來當初始化函數。可是你能夠沒有初始化函數。
類的數據 類的數據是全部類產生的對象共享的數據。這裏沒有用到類的數據,要寫的話是這樣:
代碼: |
[複製到剪貼板] |
class person: school = 'bit' def __init__(self): self.name = 'taowen' self.id = 20022479 def say_id(self): print "%s's id is %d" % (self.name, self.id) me = person() me.say_id() print me.school |
|
對象的數據 對象的數據是用 self.變量名 = 。。。 來生成的。這裏self.name就是對象的數據。對象的數據和類的數據不一樣,由於對象之間的數據是互不共享的,而類的數據是被全部由類生成的對象共享的。
對象的函數(類的函數) 兩個沒有區別,是類的就是對象的。其實就是類的(我說的是底層實現,不過不用管,若是關心怎麼實現的,等我寫Hacking OO吧,還沒影呢)。say_id就是對象的函數,你可以調用它。每一個對象的函數都須要一個self參數,表示[color]這個對象[/color]。
爲何使用面向對象編程 除去讓人以爲你比較專業外,固然由切實的好處。比較淺顯的是你可以表達必定的層次關係,類與類之間可以有包含和繼承的關係(固然你如今還不會。。。)。並且對象可以把數據和操做數據的函數放在一塊兒,可以比較清晰。雖然有所謂的數據隱藏的概念,可是在python中其實就是一個
不要直接調用對象中的數據的約定,而要用一個函數做爲中轉。其實不懂面向對象很正常,其實有的時候就是要在用的中間感悟的。何時把用函數編程用牛了,用出個道道來了,說不定你已經感受到了什麼是面向對象編程。另外:所謂什麼OO,都是一些認爲規定,不用語法支持,只要心中有這個想法(什麼想法?本身悟啊
),就可以寫出OO的代碼,無論你用的是什麼語言,什麼語法。
Lesson 12
python to exe about py2exe
本文講述如何將一個python源代碼編譯成一個exe.....我會的只是最初步最基本的.....實際上那個py2exe彷佛有着更強大的功能
1:下載安裝py2exe.....from
http://twh@bitunion.org
2:假設你寫好了一個python程序....guess_number.py.......存在了c:\Python23\下面
3:再寫一個setup.py....也存在c:\Python23\下面......內容以下
代碼: |
[複製到剪貼板] |
# setup.py from distutils.core import setup import py2exe setup(name="guess_number", scripts=["guess_number.py"], ) |
|
其中name和scripts是須要你到時候具體修改的....
4:找到windows的dos模式(命令提示符).....或者本身作個快捷方式也能夠.... C:\Python23> C:\Python23>python setup.py py2exe 構造就開始了.... 幾秒鐘之後.... 在你的C:\Python23就會出現兩個文件夾build和dist,前面那個裏面彷佛是源程序(這個我不太清楚)....dist裏面的就是編譯好的.exe了.....ok....
btw....等國兩天有了實際應用再來翻譯這些東西
Specifying additional files Some applications need additional files at runtime, this maybe configuration files, fonts, bitmaps, whatever.
py2exe can copy these files into subdirectories of dist\myscript if they are specified in the setup script with the data_files option. data_files should contain a sequence of (target-dir, files) tuples, where files is a sequence of files to be copied.
Here's an example:
代碼: |
[複製到剪貼板] |
# setup.py from distutils.core import setup import glob import py2exe setup(name="myscript", scripts=["myscript.py"], data_files=[("bitmaps", ["bm/large.gif", "bm/small.gif"]), ("fonts", glob.glob("fonts\\*.fnt"))], ) |
|
This would create a subdirectory bitmaps in dist\myscript, containing the two bitmaps, and a subdirectory fonts, containing all the *.fnt files.
相關資料出處.... http://starship.python.net/crew/theller/py2exe/
Lesson 13
寫一個簡單的界面很容易 圖形界面是很是有吸引力的東西。可是製做出來彷佛不是那麼容易,這個觀點對於用C來笨拙寫windows的窗口程序來講,是比較正確的。微軟公司出品的windows是一個圖形界面的操做系統,這個和dos或者linux這些不同,他們一開始出來是針對字符界面的,而後再在上面加上一些庫來提供圖形的功能。windows則不一樣,它是包含在本身的最原始的功能之中,而這些圖形功能的提供是在user32.dll這樣的system目錄下的dll文件中以函數導出的形式提供的,可是要使用這些東西必須使用c語言的函數接口,並且編寫麻煩。有一個很大的wndproc中要填入全部的事件處理代碼,很是醜陋。而做爲腳本語言,所應該有的簡潔性,python對這個進行了封裝。可是事情不是如你所想象。中間過程很是複雜,並且python用的也不是本身的庫,仍是tcl的一個tk的庫再封裝了一次。雖然通過層層封裝,裹得很是嚴實,可是除了影響其在比較高性能的圖形場合下的應用以外,並無帶來太大的麻煩。你可以用不多的代碼,來完成其餘語言+庫要很大行代碼才能表達的圖形樣式,雖然很是簡陋,不過足夠使用。並且python除了本身原包裝帶的這個tkinter庫以外,還有其餘的第三方的選擇,比較豐富,並且也有可以勝任各類應用的選擇。甚至,還有opengl和directx的庫的封裝庫,可以用來編寫2d和3d的遊戲,這個很是的誘人哦
。可是我不會,
圖形界面的奧祕其實並不深奧。我相信不少人學習windows編程都是從寫一個窗口開始的,並且都是從嘗試理解那個消息和事件驅動的模型入手的。大致的過程是這樣的,窗口就是用象素畫出來的。你能夠把一個窗口想象成一個窗口,也能夠把窗口當作一堆象素的集合。就像有人說看女色不過是皮肉色相同樣。並且窗口中的按鈕,編輯礦,各類圖標,不管是什麼看起來像一個」物體「的東西,其實本質上都是有應用程序或者是庫或者是操做系統調用顯卡的驅動,經過顯卡的功能在屏幕上繪畫一些點出來。而所謂的」物體「有不少稱法,在windows中通常成爲控件(control)。
而對於圖形界面的操控通常是經過鼠標和鍵盤來完成的。鼠標在屏幕上有一個本身的形象,那就是一個箭頭(固然你也能夠調整這個圖形爲其餘好玩的東西,it is your freedom)。而鍵盤呢則通常表示爲一個虛線的框,表示這個是鍵盤的」焦點「所在的地方。或者是編輯框中閃動的豎槓。這兩點中有一個共同點,就是都有一個位置來肯定要操做的對象。你點下鼠標的時候,你操做的就是鼠標的箭頭尖端指向的那個空間,而鍵盤按下也是在其焦點所在的控件那兒放聲。發生的是什麼呢?發生的過程從硬件層面到軟件層面以後,最終是被操做系統接收。操做系統可以知道你是點擊的是鼠標仍是鍵盤,在什麼一個地方點下的,並且按下的是左鍵仍是右鍵。操做系統還知道當前窗口各處擺放的位置。綜合各路的信息,操做系統就可以知道把這個」事件「做爲」消息「發送給哪一個窗口來處理。從中應該可以明白什麼叫事件,而消息呢則是一個C中的結構體,其中有幾個field中間放了有關這個事件的信息,而後就像一封信同樣從操做系統投遞到了窗口所在的應用程序。而後應用程序有一個事先註冊的」窗口過程「,其實就是一個函數,用來接收這封「信」。其實就是接收到傳過來的參數。而後再進行一些判斷,做出必定的響應。這個就是所謂的事件驅動。在沒有冗長的代碼,和展現全部細節的狀況下,若是你真的之前對這個過程一無所知,確定會以爲很是茫然。這個一筆帶過的敘述其實只是讓你有一個感性的認識。其實在python中使用窗口根本不用管諸葛麼多。基本上只是把本身要的窗口和控件,給一些位置的參數,一些文字的提示內容的參數就能把窗口擺好,顯示出來。而後再經過代碼告訴python,當「這個按鈕按下的時候執行這個函數」,而後就能讓窗口有響應。最後記得給一個退出窗口的辦法就一切OK了。其中能省的複雜度基本上都被庫給隱藏掉了。付出的代價是慢一些,可是我就不相信你能感受出來,除非你用的電腦連vcd都看不流暢。因此大可放心的享受這種便利。
OK,下面來正式的看看怎麼在python中建立一個窗口,而後顯示出來。
代碼: |
[複製到剪貼板] |
from Tkinter import * root = Tk() root.mainloop() |
|
就3行就可以把主窗口顯示出來了。root是一個變量名稱,其表明了這個主窗口。之後建立控件的時候指定控件建立在什麼窗口之中,就要用這個root來表示了。而Tk()是一個Tkinter庫之中的函數(實際上是類的構造函數,構造了一個對象)。而mainloop則是主窗口的成員函數,也就是表示讓這個root工做起來,開始接收鼠標的和鍵盤的操做。你如今就可以經過鼠標縮放以及關閉這個窗口了。注意到窗口的標題是tk,咱們能夠進行一些修改
root= Tk(className='bitunion')
而後窗口的標題就變成了bitunion了。下面要做的是把這個窗口的內容填充一下,讓其有一些東西。先加入一個標籤,所謂標籤就是一行字。
代碼: |
[複製到剪貼板] |
from Tkinter import * root = Tk(className='bitunion') label = Label(root) label['text'] = 'be on your own' label.pack() root.mainloop() |
|
咱們很驚訝的發現窗口變小了,可是其中多了一行字。變小了是由於窗口中已經放了東西了,python的Tkinter很是智能,可以根據內容自動縮放,而不用和傳統的windows程序同樣,手工的指定絕對座標了。對於label,它仍是一個變量而已。不過這個變量表明瞭一個標籤,也就是那一行字。而這個label的建立是用Label,而Label的參數是root代表了這個控件是root主窗口的成員控件,或者說是子窗口。label['text']表示設置這個標籤的text屬性爲'be on your own',也就是文字內容了。label.pack和root.mainloop同樣費解,可是內涵同樣深入。你如今能夠簡單理解爲把label顯示出來的功能,由於你把pack去掉,那你就看不到東西了。其實pack是和控件的佈局排版有關西的。
再添加一個按鈕就可以有更加豐富的內容了,方法是很相似的。看着吧:
代碼: |
[複製到剪貼板] |
from Tkinter import * root = Tk(className='bitunion') label = Label(root) label['text'] = 'be on your own' label.pack() button = Button(root) button['text'] = 'change it' button.pack() root.mainloop() |
|
只不過把button替換了label而Button替換了Label。注意一下Button和Label這些都是Tkinter這些庫提供的,而button和Button這樣大小寫之間的差異僅僅是巧合,你可以隨便的給變量取名字,可是Button和Label這些則是須要記住的東西,寫代碼的時候要常常用到的名字。可是點擊按鈕你會比較失望,由於並無什麼反應。不過也是固然的事情,你並無告訴計算機對於這樣一個按鈕的點擊操做須要做出一個什麼樣的反應來反饋給用戶。而這個指定做出什麼反應的工做只須要一個行,可是做出具體什麼樣反應的描述則須要新建一個函數來進行處理。
代碼: |
[複製到剪貼板] |
from Tkinter import * def on_click(): label['text'] = 'no way out' root = Tk(className='bitunion') label = Label(root) label['text'] = 'be on your own' label.pack() button = Button(root) button['text'] = 'change it' button['command'] = on_click button.pack() root.mainloop() |
|
button['command'] = on_click表示對於button(按鈕)的點擊屬性用on_click這個函數來處理。而on_click函數也很簡潔,只是把label的文本從新設置一下。這個完成了一個事件消息的處理,若是用C來寫,須要比這個長更加很差懂的寫法。另外你是否會對on_click中出現label這個變量比較奇怪呢?明明在on_click前面沒有定義label這個變量啊。若是我在C中這麼寫程序,編譯器必定會告訴我出錯的。而python是怎麼知道label這個變量存在,而後沒有報錯的呢?其實python在你寫的時候根本就不用知道其是否存在,只是要在運行的時候找獲得label就能夠了。而運行的先後關係,是經過時間來關聯的而不是代碼上先後行的關係。這裏因爲label = Label(root)先於on_click執行,因此當on_click執行的時候,label就是一個已經定義的變量。若是沒有定義呢?那就報告出錯嘍。
最後一個例子:
代碼: |
[複製到剪貼板] |
from Tkinter import * def on_click(): label['text'] = text.get()root = Tk(className='bitunion') label = Label(root) label['text'] = 'be on your own' label.pack() text = StringVar() text.set('change to what?') entry = Entry(root) entry['textvariable'] = text entry.pack() button = Button(root) button['text'] = 'change it' button['command'] = on_click button.pack() root.mainloop() |
|
這個就比較複雜了。裏面有一個StringVar。這個表明一個字符串,可是跟通常字符串不同。通常的這樣'dfsdf'的字符串是不可變的,你只能把變量指定爲不一樣的字符串,可是字符串自己的內容是不可改變的。而StringVar則是可變的字符串。因此了set和get來設置和取得其內容。主要是entry(單行輸入框)要求一個這樣的屬性來設置和接收其輸入框的內容。一開始可能不習慣,可是用多了以後會以爲很方便的,由於只要用這個變量text,就能一直獲得當前輸入框的內容。當你可以完整的把這個例子看懂的時候,你已經入門了。可是離本身寫一個有窗口的應用程序還有必定距離。主要是缺乏更加豐富的控件和事件響應的處理能力,以及合理排版佈局的能力。這個下次再說