模塊:在Python中,一個.py文件就稱之為一個模塊(Module)。
為了避免模塊名沖突,Python又引入了按目錄來組織模塊的方法,稱為包(Package)。例如兩個名不hello.py的模塊分別在china的包和school里的包里,然后呢,現在它們的名字分別為:china.hello與school.hello, 這樣就不沖突了吧。
每一個包目錄下面都會有一個
__init__.py的文件,這個文件是必須存在的,否則,Python就把這個目錄當成普通目錄,而不是一個包。
自己寫一個模塊:(主要學習它的格式),創建一個hello.py的文件,內容如下:
1 #!/usr/bin/python 2 # -*- coding: utf-8 -*- 3 4 'this is a hello module, i am coming ' 5 __author__='yinheyi' 6 7 import sys 8 9 def test(): 10 args = sys.argv 11 if len(args) == 1: 12 print 'hello,world' 13 print '你好,世界!' 14 elif len(args) == 2: 15 print 'hello,%s' % args[1] 16 else: 17 print '你的參數個數不對啊,我的哥!' 18 if __name__== '__main__': 19 test()第2行注釋表示.py文件本身使用標准UTF-8編碼;
第4行是一個字符串,表示模塊的文檔注釋,任何模塊代碼的第一個字符串都被視為模塊的文檔注釋;
第5行使用
__author__變量把作者寫進去,這樣當你公開源代碼后別人就可以瞻仰你的大名;注意:
if __name__=='__main__': test()當我們在命令行運行
hello模塊文件時,Python解釋器把一個特殊變量__name__置為__main__,而如果在其他地方導入該hello模塊時,則不會置為__main__, 所以我們可以直接運行這個模塊哦,用於運行測試。
給模塊起一個別名:
import 模塊名 as 別名
模塊內的變量與函數的作用域:
在一個模塊中,我們可能會定義很多函數和變量,但有的函數和變量我們希望給別人使用,有的函數和變量我們希望僅僅在模塊內部使用。在Python中,是通過
_前綴來實現的。正常的函數和變量名是公開的(public),可以被直接引用,比如:
abc,x123,PI等;類似
__xxx__這樣的變量是特殊變量,可以被直接引用,但是有特殊用途,比如上面的__author__,__name__就是特殊變量,hello模塊定義的文檔注釋也可以用特殊變量__doc__訪問,我們自己的變量一般不要用這種變量名;
類中,__xxx這樣的函數或變量就是非公開的(private),即有__開頭的名字;
模塊的搜索路經:默認情況下,Python解釋器會搜索當前目錄、所有已安裝的內置模塊和第三方模塊,搜索路徑存放在
sys模塊的path變量中。如果我們要添加搜索目錄,有兩種方法,
一是直接修改sys.path,這種方法在退出python后,會失效的。
>>> import sys >>> sys.path.append('你自己的路經')二是設置環境變量PYTHONPATH.可以在.bashrc里添加的,如,export PYTHONPATH = ‘目錄‘:$PYTHONPATH
使用__future__模塊:比如當我們是python2.7時,而我們想使用python3.4的python的功能時,怎么辦呢?我們可以從
__future__模塊里,導入我們想要用的功能。如除法:
#這是在python2.7中的 >>> 5/3 1 #導入新的; >>> from __future__ import division >>> 5/3 1.6666666666666667
面向對象的編程:它就是把一個對象作為基本單元,這個對象里有數據,也有對數據的操作方法啦。你看看C語言中,是不是以函數 為單元呢??這就是差別。例如一個水杯,它的元素就是水,它可以的操作有加水,倒水等。
面向對象編程的過程很簡單,首先創建一個類(其實,我認為就是一個數據類型啦,如int),然后再創建這個類的對象就可以啦。就好像你定義了一個汽車,然后,根據你的定義造出汽車的實例就可以啦。
類的定義,舉個例子:
#這是從 最根類繼承的,舊的方式定義Python類允許不從object類繼承,但這種編程方式已經嚴重不推薦使用。任何時 候,如果沒有合適的類可以繼承,就繼承自object類。7 class Car(object): 8 #定義一個含有的屬性啦; 9 color_ = '' 10 weight_ = 0 11 __wheel_ = 4 #可以通過__開頭開定義私有的屬性; 12 #定義它的方法; 13 def __init__(self, color, weight, wheel): 14 self.color_ = color 15 self.weight_ = weight 16 self.__wheel_ = wheel 17 def get_color(self): 18 return self.color_ 19 def get_weight(self): 20 return self.weight_ 21 def get_wheel(self): 22 return self.__wheel_ 23 24 baoma = Car('red',80,4) 25 print baoma.get_color() 26 print baoma.get_weight() 27 print baoma.get_wheel()輸出為:
red
80
4總結:
類的私有屬性:
__private_attrs 兩個下划線開頭,聲明該屬性為私有,不能在類地外部被使用或直接訪問。在類內部的方法中使用時 self.__private_attrs
類的方法
__private_method 兩個下划線開頭,聲明該方法為私有方法,不能在類地外部調用。在類的內部調用slef.__private_methods有些時候,你會看到以一個下划線開頭的實例變量名,比如
_name,這樣的實例變量外部是可以訪問的,但是,按照約定俗成的規定,當你看到這樣的變量時,意思就是,“雖然我可以被訪問,但是,請把我視為私有變量,不要隨意訪問”。雙下划線開頭的實例變量是不是一定不能從外部訪問呢?其實也不是。不能直接訪問
__name是因為Python解釋器對外把__name變量改成了_Student__name,所以,仍然可以通過_Student__name來訪問__name變量,但是不同版本的Python解釋器可能會把__name改成不同的變量名。在類地內部,使用def關鍵字可以為類定義一個方法,與一般函數定義不同,類方法必須包含參數self,且為第一個參數私有的類方法
類的專有方法:
__init__ 構造函數,在生成對象時調用
__del__ 析構函數,釋放對象時使用
__repr__ 打印,轉換
__setitem__按照索引賦值
__getitem__按照索引獲取值
__len__獲得長度
__cmp__比較運算
__call__函數調用
__add__加運算
__sub__減運算
__mul__乘運算
__div__除運算
__mod__求余運算
__pow__稱方
類的繼承與多態:我們定義一個class的時候,可以從某個現有的class繼承,新的class稱為子類(Subclass),而被繼承的class稱為基類、父類或超類
定義一個基類:
class Animal(object): def run(self): print 'Animal is running...'定義它的子類:
class Tiger(Animal): pass class Dog(Animal): def run(self): print 'Dog is running...' class Cat(Animal): def run(self): print 'Cat is running...'運行:
tiger = Tiger() tiger.run() dog = Dog() dog.run() cat = Cat() cat.run()
輸出:
Animal is running...
Dog is running... Cat is running...多態:要理解多態,你要知道上面的dog與cat的實例同時屬於Animal 與Dog 和Cat類型哦;當我們定義一個函數時,如果傳入的數據類型為Animal的話,我們可以把Animal的實例或着繼承Anaimal的類的類型傳入這個函數中。看一個例子:定義一個函數:def run_twice(animal): animal.run() animal.run()然后呢,當我們傳入Animal的實例時,run_twice()就打印出:>>> run_twice(Animal()) Animal is running... Animal is running...
當我們傳入Dog的實例時,run_twice()就打印出:>>> run_twice(Dog()) Dog is running... Dog is running...
當我們傳入Cat的實例時,run_twice()就打印出:>>> run_twice(Cat()) Cat is running... Cat is running...
可以看出:
對於Animal的子類,不必對run_twice()做任何修改,實際上,任何依賴Animal作為參數的函數或者方法都可以不加修改地正常運行,原因就在於多態。
多態的好處就是,當我們需要傳入Dog、Cat、時,我們只需要接收Animal類型就可以了,因為Dog、Cat都是Animal類型,然后,按照Animal類型進行操作即可。由於Animal類型有
run()方法,因此,傳入的任意類型,只要是Animal類或者子類,就會自動調用實際類型的run()方法,這就是多態的意思:對於一個變量,我們只需要知道它是Animal類型,無需確切地知道它的子類型,就可以放心地調用
run()方法,而具體調用的run()方法是作用在Animal、Dog、Cat對象上,由運行時該對象的確切類型決定,這就是多態真正的威力:調用方只管調用,不管細節,而當我們新增一種Animal的子類時,只要確保run()方法編寫正確,不用管原來的代碼是如何調用的。這就是著名的“開閉”原則:
對擴展開放:允許新增Animal子類;
對修改封閉:不需要修改依賴Animal類型的
run_twice()等函數。
獲取對象有信息:
判斷基本類型都可以用type()函數判斷的,如:>>> type(132) <type 'int'> >>> type('lol') <type 'str'>>>> type([1,2,3]) <type 'list'>另外,Python把每種type類型都定義好了常量,放在types模塊里,使用之前,需要先導入,可以這這樣子:>>> import types >>> type('lol')==types.StringType True >>> type([])==types.ListType True >>> type(str)==types.TypeType True對於類的話,可以使用isinstance():>>> isinstance(dog, Dog) True
使用dir()函數獲取類的對象的屬性與方法。使用
dir()函數,它返回一個包含字符串的list。#看看字符串都有哪些屬性與方法 >>> dir('lol') ['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']如,如
__len__方法返回長度。在Python中,如果你調用len()函數試圖獲取一個對象的長度,實際上,在len()函數內部,它自動去調用該對象的__len__()方法。
然后配合
hasattr(),getattr()、setattr()我們可以直接操作一個對象的狀態。
hasattr():判斷是否存在某個屬性或方法;
getattr():得到是否存在某個屬性或方法;
setattr():設置是否存在某個屬性或方法;
python作為動態語言,有很多的靈活性。
我們可以動態的能已經定義的實例綁屬性與方法哦,也可以給一個類綁定方法的。#給一個實例綁定屬性: >>> class Car(): ... pass ... >>> bmw = Car() >>> bmw.clor = 'red'
#給一個實例邦定一個方法 >>> def get_color(self): ... return self.color ... >>> from types import MethodType >>> bmw.color = MethodType(get_color, bmw, Car) >>> bmw.color() 'red'
# 給一個類邦定方法 >>> def get_color(self): ... return self.color ... >>> from types import MethodType >>> Car.color = MethodType(get_color, None, Car)
當我們想限制動態綁定的屬性的名稱時,怎么辦呢?那就利用Class的__slots__變量。
為了達到限制的目的,Python允許在定義class的時候,定義一個特殊的
__slots__變量,來限制該class能添加的屬性:>>> class Student(object): ... __slots__ = ('name', 'age') # 用tuple定義允許綁定的屬性名稱 #這樣的話,我們的Student只能動態綁定 'name'與‘age'這兩個動態變量了。另外,
使用@property裝飾器可以把定義的一個方法,變為通過屬性來調用的。
還有,很有一些特殊的變量或方法來定制類,如__len__、__str__、__iter__、__getitem__等等等 ,具體可以用到的時候具體查一下的。
python中的錯誤處理機制:
錯誤處理機制:try …except…finally
Python的錯誤其實也是class,所有的錯誤類型都繼承自BaseException。 在python程序中,一旦出現錯誤的話,它就要一級級的上報,直到某個函數能夠處理這個錯誤,如果最后沒有函數可以處理這個錯誤的話,最后就被python的解釋器捕獲,打印出錯誤信息,並退出程序了。
因為錯誤是一級一級的一報的,所以,不需要在每個可能出錯的地方去捕獲錯誤,只要在合適的層次去捕獲錯誤就可以了。
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3
4 try:
5 r = 10 /0
6 except ZeroDivisionError, sh:
7 print '出現錯誤了,except:',sh
8 finally:
9 print 'finally,錯誤機制結束'
10 print 'end,程序結束'
輸出:
yinheyi@ubuntu:~/python$ ./2.py
出現錯誤了,except: integer division or modulo by zero
finally,錯誤機制結束
end,程序結束
我們也可以利用python中的log模塊記錄錯誤信息,然后分析錯誤原因。我們在except下面加入了一個記錄錯誤的語句:
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3 import logging
4 try:
5 r = 10 /0
6 except ZeroDivisionError, sh:
7 print '出現錯誤了,except:',sh
8 logging.exception(sh)
9 finally:
10 print 'finally,錯誤機制結束'
11 print 'end,程序結束'
它的輸出為:
yinheyi@ubuntu:~/python$ ./2.py
出現錯誤了,except: integer division or modulo by zero
ERROR:root:integer division or modulo by zero
Traceback (most recent call last):
File "./2.py", line 5, in <module>
r = 10 /0
ZeroDivisionError: integer division or modulo by zero
finally,錯誤機制結束
end,程序結束
可以用raise拋出錯誤的,錯誤也可以自己定義的哦,具體,等着我用到了,我再補沖哈
另外,還有和程序的調試,測試啦等待,現在暫時用不着,不寫了就哈。(用於的時候學習代碼是效率最高的)
最后,如果你覺得以上內容對你有幫助,作為回報,那就可以打賞一下我這個窮學生吧,以資助我買幾本書。
錢也不用太多,您可以選擇:2毛,5毛、1元。
如果對你沒有幫助,那就算了。

