學習內容:html
1.類的特殊成員方法python
2.反射程序員
3.異常處理編程
4.Socket網絡編程開發基礎服務器
1.類的特殊成員方法 網絡
__doc__ 表示類的描述信息socket
1 # _*_ coding:utf-8 _*_ 2 __author__ = 'cs' 3 class Foo: 4 """類的描述信息,就是__doc__""" 5 def func(self): 6 pass 7 print Foo.__doc__
__module__ 表示當前操做的對象在那個模塊ide
__class__ 表示當前操做的對象的類是什麼函數
__init__ 構造方法,經過類建立對象時,自動觸發執行。學習
__del__
析構方法,當對象在內存中被釋放時,自動觸發執行。
注:此方法通常無須定義,由於Python是一門高級語言,程序員在使用時無需關心內存的分配和釋放,由於此工做都是交給Python解釋器來執行,因此,析構函數的調用是由解釋器在進行垃圾回收時自動觸發執行的。
__call__ 對象後面加括號,觸發執行
注:構造方法的執行是由建立對象觸發的,即:對象 = 類名() ;而對於 __call__ 方法的執行是由對象後加括號觸發的,即:對象() 或者 類()()
1 #__call__ 2 # 注:構造方法的執行是由建立對象觸發的,即:對象 = 類名() ;而對於 __call__ 方法的執行是由對象後加括號觸發的,即:對象() 或者 類()() 3 class Dog: 4 def __init__(self,name): 5 self.name = name 6 def bulk(self): 7 print("%s 汪~汪~汪" %(self.name)) 8 def __call__(self, *args, **kwargs): 9 print "I am call",args,kwargs 10 d1 = Dog("旺旺") 11 d1("aaa","bbb","cccc")
__dict__ 查看類或對象中的全部成員
1 # _*_ coding:utf-8 _*_ 2 __author__ = 'cs' 3 class Province: 4 country = 'China' 5 def __init__(self, name, count): 6 self.name = name 7 self.count = count 8 def func(self, *args, **kwargs): 9 print 'func' 10 # 獲取類的成員,即:靜態字段、方法、 11 print Province.__dict__ 12 # obj1 = Province('HuBei',10000) 13 # print obj1.__dict__ 14 # 獲取 對象obj1 的成員 15 obj2 = Province('HuNan', 3888) 16 # print obj2.__dict__ 17 # 獲取 對象obj1 的成員
__str__ 若是一個類中定義了__str__方法,那麼在打印對象時,默認輸出該方法的返回值。
python3中使用,python建議使用__unicode__
1 # _*_ coding:utf-8 _*_ 2 __author__ = 'cs' 3 class Role(object): 4 def __init__(self,name,role,weapon,life_value=100,money=15000): 5 self.name = name 6 self.role = role 7 self.weapon = weapon 8 self.life_value = life_value 9 self.money = money 10 def shot(self): 11 print("shooting...") 12 def got_shot(self): 13 print("%s: ah...,I got shot..."%self.name) 14 def buy_gun(self,gun_name): 15 print("just bought %s" %gun_name) 16 # def __str__(self): 17 # print("name is %s"%self.name) 18 # return "name is %s"%self.name 19 20 r1 = Role("A","P","Ak47") 21 print(r1)
__getitem__、__setitem__、__delitem__
用於索引操做,如字典。以上分別表示獲取、設置、刪除數據
1 # _*_ coding:utf-8 _*_ 2 __author__ = 'cs' 3 #把這個實例變成字典 4 class Foo(object): 5 def __init__(self): 6 self.data = {} 7 def __getitem__(self, key): 8 print('__getitem__',key) #('__getitem__', 'name') 9 return self.data.get(key) 10 def __setitem__(self, key, value): 11 print('__setitem__',key,value) 12 self.data[key] = value 13 def __delitem__(self, key): 14 print('__delitem__',key) 15 16 17 obj = Foo() #實例化後,就成了字典 18 obj["name"] = "lw" #能夠像字典同樣賦值,自動觸發執行 __setitem__ 19 result = obj['name'] # 自動觸發執行 __getitem__ 20 print(result) 21 print(obj.data) #打印這個字典 22 del obj['name'] #只是觸發__delitem__,並無真的刪除,要想刪除在__delitem__這個函數下面刪除,若是不想讓用戶刪除某些key,能夠加判斷 23 print(obj.data) 24 # del obj['k1']
2.反射
經過字符串映射或修改程序運行時的狀態、屬性、方法, 有如下4個方法
hasattr:判斷object中有沒有一個name字符串對應的方法或屬性
getattr:根據字符串去獲取對象裏的方法對應的內存地址
setattr :s equivalent to ``x.y = v''
delattr(x, y)
例1:
1 # _*_ coding:utf-8 _*_ 2 __author__ = 'cs' 3 def bulk(self): #這裏會將函數設置成類裏面的方法 4 print("%s is bulking"%self.name) 5 class Dog(object): 6 7 def __init__(self,name): 8 self.name = name 9 def eat(self,age): 10 11 print("%s is eating.."%self.name) 12 13 d = Dog("金毛") 14 # d.eat() 15 choice = raw_input(">>>:").strip() 16 # d.choice 想實現這種調用,根據用戶輸入調用方法,可是不能這麼寫,由於choic是個字符串 17 print(hasattr(d,choice)) #查看類中是否有用戶輸入的方法或者屬性,有打印True,沒有打印False 18 # print(getattr(d,choice)) #這樣會打印這個方法的內存地址,加上()就調用了 19 # getattr(d,choice)() #調用 20 #------------------------------ 21 # print(d.name) 22 # setattr(d,"name",choice) 23 # print(d.name) 24 #------------------------------- 25 # setattr(d,choice,"22") 26 # print(getattr(d,choice)) 27 # print(hasattr(d,choice)) 28 #------------------------------ 29 #動態添加變量 30 # if hasattr(d,choice): 31 # getattr(d,choice) 32 # else: 33 # setattr(d,choice,"ccc") 34 # V = getattr(d,choice) 35 # print(V) 36 #--------------------------- 37 #動態設置方法,不管用戶輸入什麼,都不會報錯,均可以調用方法 38 # if hasattr(d,choice): 39 # getattr(d,choice) 40 # else: 41 # setattr(d,choice,bulk) #d.talk == bulk 42 # func = getattr(d,choice) #獲取choic的內存地址 43 # func(d) 44 45 # ---------------------- 46 # print(hasattr(d,choice)) 47 # getattr(d,choice)() 48 # print(d.name) 49 # if hasattr(d,choice): 50 # delattr(d,choice) 51 # else: 52 # print("dont") 53 # print(d.name) 54 # delattr(d,choice) 55 # if hasattr(d,choice): 56 # getattr(d,choice)() 57 # 58 # else: 59 # # print("沒有這個方法")
例2:
1 class Foo(object): 2 3 def __init__(self): 4 self.name = 'wupeiqi' 5 6 def func(self): 7 return 'func' 8 9 obj = Foo() 10 11 # #### 檢查是否含有成員 #### 12 hasattr(obj, 'name') 13 hasattr(obj, 'func') 14 15 # #### 獲取成員 #### 16 getattr(obj, 'name') 17 getattr(obj, 'func') 18 19 # #### 設置成員 #### 20 setattr(obj, 'age', 18) 21 setattr(obj, 'show', lambda num: num + 1) 22 23 # #### 刪除成員 #### 24 delattr(obj, 'name') 25 delattr(obj, 'func')
例3:
1 # __author__ = 'cs' 2 def dulk(): 3 print("%s is ...") 4 class Dog(object): 5 def __init__(self,name): 6 self.name = name 7 def eat(self): 8 print("%s is eating..." %self.name) 9 d = Dog("niuhanyang") 10 choice = input(">>:").strip() #輸入的是Dog這個類裏面的方法---->eat 11 if hasattr(d,choice): #判斷choice(輸入的)字符串在d(類)裏面是否存在 12 #print(getattr(d,choice)) #獲取方法並打印 13 getattr(d,choice)() #獲取方法並執行 14 else: 15 setattr(d,choice,dulk) #d.choice = dulk的內存地址 16 fun = getattr(d,choice) 17 fun()
3.異常處理
參考 http://www.cnblogs.com/wupeiqi/articles/5017742.html
一、異常基礎
在編程過程當中爲了增長友好性,在程序出現bug時通常不會將錯誤信息顯示給用戶,而是現實一個提示的頁面,通俗來講就是不讓用戶看見大黃頁!!!
1 try: 2 pass 3 except Exception,ex: 4 pass
需求:將用戶輸入的兩個數字相加
1 while True: 2 num1 = raw_input('num1:') 3 num2 = raw_input('num2:') 4 try: 5 num1 = int(num1) 6 num2 = int(num2) 7 result = num1 + num2 8 except Exception, e: 9 print '出現異常,信息以下:' 10 print e
二、異常種類
python中的異常種類很是多,每一個異常專門用於處理某一項異常!!!
1 AttributeError 試圖訪問一個對象沒有的樹形,好比foo.x,可是foo沒有屬性x 2 IOError 輸入/輸出異常;基本上是沒法打開文件 3 ImportError 沒法引入模塊或包;基本上是路徑問題或名稱錯誤 4 IndentationError 語法錯誤(的子類) ;代碼沒有正確對齊 5 IndexError 下標索引超出序列邊界,好比當x只有三個元素,卻試圖訪問x[5] 6 KeyError 試圖訪問字典裏不存在的鍵 7 KeyboardInterrupt Ctrl+C被按下 8 NameError 使用一個還未被賦予對象的變量 9 SyntaxError Python代碼非法,代碼不能編譯(我的認爲這是語法錯誤,寫錯了) 10 TypeError 傳入對象類型與要求的不符合 11 UnboundLocalError 試圖訪問一個還未被設置的局部變量,基本上是因爲另有一個同名的全局變量, 12 致使你覺得正在訪問它 13 ValueError 傳入一個調用者不指望的值,即便值的類型是正確的
1 ArithmeticError 2 AssertionError 3 AttributeError 4 BaseException 5 BufferError 6 BytesWarning 7 DeprecationWarning 8 EnvironmentError 9 EOFError 10 Exception 11 FloatingPointError 12 FutureWarning 13 GeneratorExit 14 ImportError 15 ImportWarning 16 IndentationError 17 IndexError 18 IOError 19 KeyboardInterrupt 20 KeyError 21 LookupError 22 MemoryError 23 NameError 24 NotImplementedError 25 OSError 26 OverflowError 27 PendingDeprecationWarning 28 ReferenceError 29 RuntimeError 30 RuntimeWarning 31 StandardError 32 StopIteration 33 SyntaxError 34 SyntaxWarning 35 SystemError 36 SystemExit 37 TabError 38 TypeError 39 UnboundLocalError 40 UnicodeDecodeError 41 UnicodeEncodeError 42 UnicodeError 43 UnicodeTranslateError 44 UnicodeWarning 45 UserWarning 46 ValueError 47 Warning 48 ZeroDivisionError 49 50 更多異常
1 dic = ["wupeiqi", 'alex'] 2 try: 3 dic[10] 4 except IndexError, e: 5 print e
1 dic = {'k1':'v1'} 2 try: 3 dic['k20'] 4 except KeyError, e: 5 print e
1 s1 = 'hello' 2 try: 3 int(s1) 4 except ValueError, e: 5 print e
對於上述實例,異常類只能用來處理指定的異常狀況,若是非指定異常則沒法處理。
1 # 未捕獲到異常,程序直接報錯 2 3 s1 = 'hello' 4 try: 5 int(s1) 6 except IndexError,e: 7 print e
因此,寫程序時須要考慮到try代碼塊中可能出現的任意異常,能夠這樣寫:
1 s1 = 'hello' 2 try: 3 int(s1) 4 except IndexError,e: 5 print e 6 except KeyError,e: 7 print e 8 except ValueError,e: 9 print e
萬能異常 在python的異常中,有一個萬能異常:Exception,他能夠捕獲任意異常,即:
1 s1 = 'hello' 2 try: 3 int(s1) 4 except Exception,e: 5 print e
接下來你可能要問了,既然有這個萬能異常,其餘異常是否是就能夠忽略了!
答:固然不是,對於特殊處理或提醒的異常須要先定義,最後定義Exception來確保程序正常運行。
1 s1 = 'hello' 2 try: 3 int(s1) 4 except KeyError,e: 5 print '鍵錯誤' 6 except IndexError,e: 7 print '索引錯誤' 8 except Exception, e: 9 print '錯誤'
三、異常其餘結構
1 try: 2 # 主代碼塊 3 pass 4 except KeyError,e: 5 # 異常時,執行該塊 6 pass 7 else: 8 # 主代碼塊執行完,執行該塊 9 pass 10 finally: 11 # 不管異常與否,最終執行該塊 12 pass
四、主動觸發異常
1 try: 2 raise Exception('錯誤了。。。') 3 except Exception,e: 4 print e
五、自定義異常
1 class WupeiqiException(Exception): 2 3 def __init__(self, msg): 4 self.message = msg 5 6 def __str__(self): 7 return self.message 8 9 try: 10 raise WupeiqiException('個人異常') 11 except WupeiqiException,e: 12 print e
六、斷言
1 # assert 條件 2 3 assert 1 == 1 4 5 assert 1 == 2
4.Socket網絡編程開發基礎
參考:http://www.cnblogs.com/wupeiqi/articles/5040823.html
socket一般也稱做"套接字",用於描述IP地址和端口,是一個通訊鏈的句柄,應用程序一般經過"套接字"向網絡發出請求或者應答網絡請求。
socket起源於Unix,而Unix/Linux基本哲學之一就是「一切皆文件」,對於文件用【打開】【讀寫】【關閉】模式來操做。socket就是該模式的一個實現,socket便是一種特殊的文件,一些socket函數就是對其進行的操做(讀/寫IO、打開、關閉)
socket和file的區別:
socket server:
1 #-*-coding:utf-8-*- 2 #服務器端 3 4 import socket 5 server = socket.socket() 6 server.bind(('localhost',6969)) #綁定要監聽端口 7 server.listen(5) #監聽 8 9 print("我要開始等電話了") 10 while True: 11 conn, addr = server.accept() # 等電話打進來 12 # conn就是客戶端連過來而在服務器端爲其生成的一個鏈接實例 13 print(conn, addr) 14 print("電話來了") 15 count = 0 16 while True: 17 data = conn.recv(1024) 18 print("recv:",data) 19 if not data: 20 print("client has lost...") 21 break 22 conn.send(data.upper()) 23 count+=1 24 if count >10:break 25 26 server.close()
socket client:
1 #客戶端 2 import socket 3 4 client = socket.socket() #聲明socket類型,同時生成socket鏈接對象 5 client.connect(('localhost',6969)) 6 7 while True: 8 msg = input(">>:").strip() 9 if len(msg) == 0:continue 10 client.send(msg.encode("utf-8")) 11 data = client.recv(10240) 12 print("recv:",data.decode()) 13 14 client.close()
WEB服務應用:
1 #!/usr/bin/env python 2 #coding:utf-8 3 import socket 4 5 def handle_request(client): 6 buf = client.recv(1024) 7 client.send("HTTP/1.1 200 OK\r\n\r\n") 8 client.send("Hello, World") 9 10 def main(): 11 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 12 sock.bind(('localhost',8080)) 13 sock.listen(5) 14 15 while True: 16 connection, address = sock.accept() 17 handle_request(connection) 18 connection.close() 19 20 if __name__ == '__main__': 21 main()
更多功能
sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0)
參數一:地址簇
socket.AF_INET IPv4(默認)
socket.AF_INET6 IPv6socket.AF_UNIX 只可以用於單一的Unix系統進程間通訊
參數二:類型
socket.SOCK_STREAM 流式socket , for TCP (默認)
socket.SOCK_DGRAM 數據報式socket , for UDPsocket.SOCK_RAW 原始套接字,普通的套接字沒法處理ICMP、IGMP等網絡報文,而SOCK_RAW能夠;其次,SOCK_RAW也能夠處理特殊的IPv4報文;此外,利用原始套接字,能夠經過IP_HDRINCL套接字選項由用戶構造IP頭。
socket.SOCK_RDM 是一種可靠的UDP形式,即保證交付數據報但不保證順序。SOCK_RAM用來提供對原始協議的低級訪問,在須要執行某些特殊操做時使用,如發送ICMP報文。SOCK_RAM一般僅限於高級用戶或管理員運行的程序使用。
socket.SOCK_SEQPACKET 可靠的連續數據包服務參數三:協議
0 (默認)與特定的地址家族相關的協議,若是是 0 ,則系統就會根據地址格式和套接類別,自動選擇一個合適的協議
UDP Demo1 import socket 2 ip_port = ('127.0.0.1',9999) 3 sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0) 4 sk.bind(ip_port) 5 6 while True: 7 data = sk.recv(1024) 8 print data 9 10 11 12 13 import socket 14 ip_port = ('127.0.0.1',9999) 15 16 sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0) 17 while True: 18 inp = raw_input('數據:').strip() 19 if inp == 'exit': 20 break 21 sk.sendto(inp,ip_port) 22 23 sk.close() 24
sk.bind(address)
s.bind(address) 將套接字綁定到地址。address地址的格式取決於地址族。在AF_INET下,以元組(host,port)的形式表示地址。
sk.listen(backlog)
開始監聽傳入鏈接。backlog指定在拒絕鏈接以前,能夠掛起的最大鏈接數量。
backlog等於5,表示內核已經接到了鏈接請求,但服務器尚未調用accept進行處理的鏈接個數最大爲5
這個值不能無限大,由於要在內核中維護鏈接隊列
sk.setblocking(bool)
是否阻塞(默認True),若是設置False,那麼accept和recv時一旦無數據,則報錯。
sk.accept()
接受鏈接並返回(conn,address),其中conn是新的套接字對象,能夠用來接收和發送數據。address是鏈接客戶端的地址。
接收TCP 客戶的鏈接(阻塞式)等待鏈接的到來
sk.connect(address)
鏈接到address處的套接字。通常,address的格式爲元組(hostname,port),若是鏈接出錯,返回socket.error錯誤。
sk.connect_ex(address)
同上,只不過會有返回值,鏈接成功時返回 0 ,鏈接失敗時候返回編碼,例如:10061
sk.close()
關閉套接字
sk.recv(bufsize[,flag])
接受套接字的數據。數據以字符串形式返回,bufsize指定最多能夠接收的數量。flag提供有關消息的其餘信息,一般能夠忽略。
sk.recvfrom(bufsize[.flag])
與recv()相似,但返回值是(data,address)。其中data是包含接收數據的字符串,address是發送數據的套接字地址。
sk.send(string[,flag])
將string中的數據發送到鏈接的套接字。返回值是要發送的字節數量,該數量可能小於string的字節大小。即:可能未將指定內容所有發送。
sk.sendall(string[,flag])
將string中的數據發送到鏈接的套接字,但在返回以前會嘗試發送全部數據。成功返回None,失敗則拋出異常。
內部經過遞歸調用send,將全部內容發送出去。
sk.sendto(string[,flag],address)
將數據發送到套接字,address是形式爲(ipaddr,port)的元組,指定遠程地址。返回值是發送的字節數。該函數主要用於UDP協議。
sk.settimeout(timeout)
設置套接字操做的超時期,timeout是一個浮點數,單位是秒。值爲None表示沒有超時期。通常,超時期應該在剛建立套接字時設置,由於它們可能用於鏈接的操做(如 client 鏈接最多等待5s )
sk.getpeername()
返回鏈接套接字的遠程地址。返回值一般是元組(ipaddr,port)。
sk.getsockname()
返回套接字本身的地址。一般是一個元組(ipaddr,port)
sk.fileno()
套接字的文件描述符