1.集合的概念html
集合是一個無序的,不重複的數據組合,它的主要做用以下python
*去重,把一個列表變成集合,就自動去重了linux
*關係測試,測試兩組數據以前的交集、並集、差集、子集、父級、對稱差集,判斷沒有交集等關係git
2.經常使用操做:程序員
1):集合的增刪改查:算法
1 #http://www.cnblogs.com/Jame-mei 2 #集合的增刪改查等基本操做 3 4 list1=set([1,3,5,7]) 5 6 #1.增長 7 list1.add(9) #添加單項,update添加多項。 8 list1.add('a') 9 print (list1): 10 {1, 3, 5, 7, 9,'a'} 11 12 ======================================= 13 #2.刪除 14 list1.remove(1) #刪除指定單個,若是指定不存在報錯 15 list1.pop() #刪除任意並返回 16 list1.discard('absdf') ##刪除指定單個,若是指定不存在返回None值(不報錯) 17 18 print (list1): 19 {3, 5, 7} 20 ======================================= 21 22 #3.修改 23 list1.update([2,4,6]) #注意這裏格式,爲列表的格式!! 24 list1.update(['a','A','b','C']) 25 print (list1)#(輸出後,會添加到集合裏,順序是隨機的!) 26 {1, 2, 3, 4, 5, 6, 7, 'b', 'C', 'a', 'A'} 27 28 29 list2=set('123') #注意這裏的類型爲字符串類型! 30 list2.update('456') 31 list3.update(('123','789')) 32 print (list2) 33 print (list2)#(輸出後,會添加到即合理裏,順序是隨機的!) 34 {'6', '2', '4', '5', '1', '3','123','456','789'} 35 36 37 38 list3=set((1,2,3,4)) #注意這裏的類型爲元祖! 39 list3.update((456,)) #添加單個元祖的時候,必需要加,逗號,否則會報錯。 40 print (list3) # 41 {1, 2, 3, 4, 456} 42 43 44 list4=set({'name':'小明','sex':'男'}) #添加字典到集合中 45 list4.update({'age':25,'address':'abc'}) 46 47 print (list4)#輸出後,只有key 48 {'sex', 'name', 'address', 'age'} 49 50 51 ======================================== 52 53 #4.查看 54 55 #1):長度 56 print(len(list1)) 57 58 #2):查看元素是否在集合中(列表,字典,集合,字符串均可以用in 或者not in來判斷!!!) 59 print (5 in list1) 60 #3):查看元素是否不是list1中 61 print (9 not in list1) 62 63 #4):測試list1是不是list2的子集 64 list2=set([1,3,5,7,9]) 65 66 67 print(list1.issubset(list2)) 68 #運算符 69 print (list1<=list2) 70 71 #5):測試list2是不是list1的父級 72 print(list2.issuperset(list1)) 73 #運算符 74 print (list2>=list1) 75 76 #還有並集 | ,差集 - ,對稱差集 ^,淺coyp: list1.copy等等
2):常見的集合運算和集合運算符shell
1 #Author Jame-Mei 2 3 #1.去除除列表中重複值 4 list1=[1,3,5,7,1,2,4,7] 5 6 list1=set(list1) 7 print (list1,type(list1)) 8 9 output: 10 {1, 2, 3, 4, 5, 7} <class 'set'> 11 =========================================================================================>>>>>>>> 12 13 14 #2.取交集:關係測試 15 list1=set([1,3,6,7,9]) 16 list2=set([2,4,6,7,8]) 17 #其中重複爲6,7 18 print (list1,list2): 19 {1, 3, 6, 7, 9} {2, 4, 6, 7, 8} 20 21 #list3爲交集的元素 22 list3=list1.intersection(list2) 23 print (list3): 24 {6, 7} 25 26 #交集元算符:& (兩邊無前後順序) 27 list1 & list2 28 =========================================================================================>>>>>>>> 29 30 31 #2.取並:union() 32 list1=set([1,3,5]) 33 list2=set([2,4,6]) 34 35 list3=list1.union(list2) 36 print (list3): 37 {1, 2, 3, 4, 5, 6} 38 39 #並集運算符:| (兩邊無前後順序) 40 list1 | list2 41 =========================================================================================>>>>>>>> 42 43 44 #3.差集:求list1和list2共有的之外的,各自的元素。 45 list1=set([1,3,5,7,9]) 46 list2=set([2,4,6,7,9]) 47 48 #取list1的差集,list2中沒有的,屬於list1的。 49 list3=list1.difference(list2) 50 print (list3): 51 {1, 3, 5} 52 53 #取list2的差集,list1中沒有的,屬於list2的。 54 list4=list2.difference(list1) 55 print (list4): 56 {2, 4, 6} 57 58 #差集運算符: - (在左邊,不在右邊) 59 list1 - list2 60 61 list2 - list1(差集的元素在list2中,不在list1中) 62 =========================================================================================>>>>>>>> 63 64 65 #4.子集:list1是不是list2的子集(兒子),list1裏面有的list2都有,list2裏面有的,list1不必定有(list2包括list1) 66 list1=set([1,3,5]) 67 list2=set([1,3,5,7,9]) 68 print (list1.issubset(list2)): 69 True 70 =========================================================================================>>>>>>>> 71 72 73 74 #5.父級:list1是不是list2的父級(父親),list1包括list2,list1裏面有的list不必定有,list2有的list1必定有。 75 list2=set([1,3,5]) 76 list1=set([1,3,5,7,9]) 77 print(list1.issuperset(list2)): 78 True 79 =========================================================================================>>>>>>>> 80 81 82 #6.對稱差集:去除2者重複後的全部元素,或者這二者的差集相加,(互相都沒有的和)就是對稱差集。 83 list2=set([1,3,5,8,10,12]) 84 list1=set([1,3,5,7,9]) 85 86 print (list1.symmetric_difference(list2)): 87 {7, 8, 9, 10, 12} 88 89 #對稱差集的元算符: ^ (返回一個新的 set 包含 list1 和 list2 中不重複的元素 ,無順序關係!) 90 list1 ^ list2 91 92 =========================================================================================>>>>>>>> 93 #7.判斷沒有交集,True=沒有交集,False=有交集。 94 list1=set([1,3,5]) 95 list2=set([2,4,6]) 96 97 flag=list1.isdisjoint(list2) 98 print(flag): 99 True
*對文件操做流程:編程
1):打開文件,獲得文件句柄並賦值給一個變量windows
2):經過句柄對文件進行操做python3.x
3):關閉文件
*打開文件的模式有:
"+" 表示能夠同時讀寫某個文件:
"U"表示在讀取時,能夠將 \r \n \r\n自動轉換成 \n (與 r 或 r+ 模式同使用)
"b"表示處理二進制文件(如:FTP發送上傳ISO鏡像文件,linux可忽略,windows處理二進制文件時需標註)
1.文件的基本操做
1 #Author:Jame Mei 2 #在當前目錄新建yesterdaytext和yesterday兩個文件 3 4 '''#1.默認方式爲'r'的方式打開讀取文件 5 file1=open("yesterdaytext",encoding='UTF-8').read() 6 print (file1) 7 ''' 8 9 10 """ 11 #2.讀取改進款,f爲文件句柄(記錄文件的文件名、文件位置,文件大小等等),'r'打開文件的模式:注意位置,不寫默認r模式。 12 f=open('yesterdaytext','r',encoding='utf-8') 13 data1=f.read() 14 data2=f.read() 15 print (data1) #data1正常輸出!! 16 print ("=========data2=====發現data2爲空....沒法再從頭讀一遍!===") 17 print (data2) 18 """ 19 20 '''#3.寫覆蓋模式w 21 f=open("yesterday",'w',encoding='utf-8') 22 f.write("我愛北京天安門\n") 23 f.write("天安門上紅旗飄揚") 24 ''' 25 26 '''#4.寫追加模式a 27 f=open("yesterday",'a',encoding='utf-8') 28 29 f.write("one night beijin,我留下不少情!") 30 f.write('\n不敢在午夜問路,怕驚醒了帝都的魂!') 31 '''
2.文件操做的一些方法
1 #Author http://www.cnblogs.com/Jame-mei 2 3 '''#1.讀文件的前五行 4 f=open('yesterdaytext','r',encoding='utf-8') 5 6 方法1:(計數法) 7 count=0 8 for line in f: 9 if count<5: 10 print (line.strip()) 11 else: 12 break 13 count+=1 14 15 方法2:(最簡法) 16 for i in range(5): 17 print (f.readline().strip()) 18 19 方法3:(取小標法) 20 for index,line in enumerate(f.readlines()): 21 if index<5: 22 print (line.strip()) 23 else: 24 break 25 ''' 26 27 28 '''#2.讀取文件,跳過第十行顯示分割線(打印出來發現第十行被print覆蓋了,源文件沒改變)! 29 f=open('yesterdaytext','r',encoding='utf-8') 30 方法1:(下標法) 31 for index,line in enumerate(f.readlines()): 32 if index==9: 33 print ('-------------------------------------我是分割線------------------------------') 34 continue 35 print (line.strip()) 36 37 38 方法2:計數法: 39 count=0 40 for line in f: 41 if count==9: 42 print ('----------------------第10行分割線--------------------') 43 else: 44 print (line.strip()) 45 count+=1 46 47 ''' 48 49 '''#3.readline只適合讀取小文件,用下面的方式來讀,效率高,內存中只保存一行,適合數據了大的場景!! 50 #f至關於迭代器 51 count=0 52 f=open('yesterdaytext','r',encoding='utf-8') 53 for line in f: 54 if count==9: 55 print ('---------------------------過濾第10行-------------------------->>>>>>>>>>>>>>') 56 count += 1 57 continue 58 print (line.strip()) 59 count+=1 60 ''' 61 62 '''#4.對於read()讀過一遍後,沒法再從頭讀,進行解答。 63 #重要函數readline(),seek()! 64 上文疑問實例預覽: 65 data1=f.read() 66 data2=f.read() 67 print (data1) #data1正常輸出!! 68 print ("=========data2=====發現data2爲空....沒法再從頭讀一遍!===") 69 print (data2) 70 71 #解決: 72 f=open('yesterdaytext','r',encoding='utf-8') 73 print (f.tell()) #告訴目前光標的位置! 74 print (f.readline()) #讀取一行 75 print (f.readline()) #讀取2行後,我如今想返回? 76 #print (f.read(5)) #去讀指定的個數字符 77 print (f.tell()) 78 79 f.seek(0)#返回開頭的光標的位置! 80 #f.seek(10) #把光標移動到第10個字符前,readline()從第10個字符讀到第一行的結尾。 81 print (f.readline()) 82 print (f.tell()) #又到了讀完第一行的光標位置! 83 ''' 84 85 '''#5.enconding()方法,fileno()方法讀取文件的內存裏的編號,isatty()判斷是否一個底層不可打印設備。 86 f=open('yesterdaytext','r',encoding='utf-8') 87 print(f.encoding): 88 utf-8 89 print (f.fileno()): 90 3 91 print (f.isatty()): 92 False 93 ''' 94 95 '''#6.seekable ,判斷是否能夠移動。readable(),writeable() 96 f=open('yesterdaytext','r',encoding='utf-8') 97 98 print (f.seekable()): 99 True 100 print (f.readable()): 101 True 102 print (f.writable()): 103 False 104 ''' 105 106 '''#7.flush(),在windows或者linux的終端窗口下效果比較明顯,防止斷電沒有從內存中寫入到磁盤。 107 #closed判斷文件是否關閉了,沒有關閉False! 108 f=open('yesterday02','w',encoding='utf-8') 109 f.write("hello") #在dos下寫過以後,查看yesterday02並無寫入,flush()以後才能看到存儲到文件中。 110 f.flush() 111 112 print (f.closed): 113 False 114 ''' 115 116 '''#8.truncate()截斷,w若是不寫會清空文件,a若是不寫默認不操做。寫了10,從第10個字符截斷,後面的刪除。 117 f=open('yesterday02','a',encoding='utf-8') 118 #f.truncate() 119 f.seek(10) #光標跳到第10個字符,截圖前20個,後面的刪除!! 120 f.truncate(20) 121 '''
實現windows or linux安裝進度條打印效果:
1 #Author:Jame Mei 2 import sys,time 3 4 #實現windows安裝進度條顯示.......... 5 for i in range(30): 6 sys.stdout.write("#") 7 sys.stdout.flush() 8 time.sleep(0.3)
3.文件操做的重要參數操做:
r+、w+、a+、rb、wb等
1 #Author: http://www.cnblogs.com/Jame-mei 2 '''#1.open()的r+(讀寫)參數實例,打開讀並追加這個比較經常使用!! 3 f=open('yesterdaytext','r+',encoding='utf-8') 4 count=0 5 for lin in f: 6 if count==3: 7 f.write("\n>>>>>打印前三行,開始w的操做>>>") #發現不管如何都沒法在第三行以後寫,只能從最後開始追加寫入!! 8 count+=1 9 10 print(f.readline()) 11 count+=1 12 ''' 13 14 15 '''#2.open()的w+(寫讀)參數實例,依然和r+同樣,只能從文件的末尾追加寫入!這個應用場景比較少 16 f=open('yesterday02','w+',encoding='utf-8') 17 f.write("123456789\n") 18 f.write("23456789\n") 19 f.write("3456789\n") 20 21 print(f.tell()) 22 f.seek(10) 23 print (f.tell()) 24 25 print (f.readline()) 26 27 f.write("456789") 28 f.close() 29 ''' 30 31 32 33 '''#3.open()的a+ 追加讀寫,a不能讀其餘和a+同樣 34 f=open('yesterdaytext','a+',encoding='utf-8') 35 f.seek(0) #若是不移動到文件開頭,讀出來的爲空白! 36 37 print(f.readline()) 38 39 f.write('a+++++++光標移動到開始了,依然會追加到末尾!') 40 #a+存在則光標移動到最後,不存在則建立。 41 ''' 42 43 44 #4.open()的rb,wb:以二進制格式打開一個文件用於只讀。文件指針將會放在文件的開頭。這是默認模式。通常用於非文本文件如圖片等。 45 '''f=open('yesterdaytext','rb') #能夠以2進制的方式讀出來,不進行解碼decode()的話,會帶b''的方式顯示。 46 print (f.readline()) 47 print (f.readline().decode()) #解碼成utf-8格式顯示 48 #若是不去掉enconfing='utf-8'則會valueError: binary mode doesn't take an encoding argument 49 50 51 #rb+以二進制格式打開一個文件用於讀寫。文件指針將會放在文件的開頭。通常用於非文本文件如圖片等。 52 f=open('yesterday02','rb+') 53 print (f.readline()) 54 f.write("2222".encode()) #會在第二行寫入,在這行甚至後面行會被覆蓋! 55 print (f.readline()) 56 f.write("111111111111111".encode()) 57 58 59 60 #wb以二進制格式打開一個文件只用於寫入。若是該文件已存在則將其覆蓋。若是該文件不存在,建立新文件。通常用於非文本文件如圖片等。 61 f=open('yesterday02','wb') #二進制寫模式,要把字符串轉換bytes 62 f.write("cedfg".encode()) #encode默認utf-8 63 #字符串若是不轉換成bytes,則出現:TypeError: a bytes-like object is required, not 'str' 64 65 66 #wb+以二進制格式打開一個文件用於讀寫。若是該文件已存在則將其覆蓋。若是該文件不存在,建立新文件。通常用於非文本文件如圖片等。 67 f=open('yesterday02','wb+') 68 print (f.readline().decode()) 69 f.write('2222222222222222'.encode()) 70 '''
4.with語句
爲了不打開文件後忘記關閉,能夠經過管理上下文,即:
1
2
3
|
with
open
(
'log'
,
'r'
) as f:
...
|
如此方式,當with代碼塊執行完畢時,內部會自動關閉並釋放文件資源。
在Python 2.7 後,with又支持同時對多個文件的上下文進行管理,即:
1
2
|
with
open
(
'log1'
) as obj1,
open
(
'log2'
) as obj2:
pass
|
Python官方建議若是一行不要超過80個字符,因此建議同時打開過個文件的時候這樣寫比較規範,並且方便觀看:
1.修改文件中的內容:
思路1:找到須要修改的地方後,修改後另存到新的文件中。
思路2:須要打開2個文件,一個文件讀r,一個文件負責寫w。
1 f_old=open('yesterdaytext','r',encoding='utf-8') 2 f_new=open('yesterdaytext.bak','w',encoding='utf-8') 3 ''' 4 for line in f_old: 5 if '肆意的快樂等我享受' in line: 6 line=line.replace('肆意的快樂等我享受','肆意的快樂等Jame享受') 7 8 f_new.write(line) #省略if下面和else下面都寫這句,反正都須要執行的操做。 9 10 11 f_old.close() 12 f_new.close()
2.做業程序練習
程序1: 實現簡單的shell sed替換功能
1 #Author Jame-Mei 2 import sys 3 4 f_old=open('oldfile','r',encoding='utf-8') 5 f_new=open('oldfile.bak','w',encoding='utf-8') 6 7 find_str=sys.argv[1] #向腳本里傳須要查找字符串-參數1 8 replace_str=sys.argv[2] #向腳本傳替換的字符串-參數2 9 10 for line in f_old: 11 if find_str in line: 12 line=line.replace(find_str,replace_str) 13 14 f_new.write(line) #去除else,更加簡潔 15 16 f_old.close() 17 f_new.close()
程序2:修改haproxy配置文件
需求以下:
1 需求: 2 一、查 3 輸入:www.oldboy.org 4 獲取當前backend下的全部記錄 5 6 二、新建 7 輸入: 8 arg = { 9 'bakend': 'www.oldboy.org', 10 'record':{ 11 'server': '100.1.7.9', 12 'weight': 20, 13 'maxconn': 30 14 } 15 } 16 17 三、刪除 18 輸入: 19 arg = { 20 'bakend': 'www.oldboy.org', 21 'record':{ 22 'server': '100.1.7.9', 23 'weight': 20, 24 'maxconn': 30 25 } 26 } 27 28 29 原配置文件: 30 global 31 log 127.0.0.1 local2 32 daemon 33 maxconn 256 34 log 127.0.0.1 local2 info 35 defaults 36 log global 37 mode http 38 timeout connect 5000ms 39 timeout client 50000ms 40 timeout server 50000ms 41 option dontlognull 42 43 listen stats :8888 44 stats enable 45 stats uri /admin 46 stats auth admin:1234 47 48 frontend oldboy.org 49 bind 0.0.0.0:80 50 option httplog 51 option httpclose 52 option forwardfor 53 log global 54 acl www hdr_reg(host) -i www.oldboy.org 55 use_backend www.oldboy.org if www 56 57 backend www.oldboy.org 58 server 100.1.7.9 100.1.7.9 weight 20 maxconn 3000
實現過程:
1):流程思惟導圖
2):代碼
1 # Author: www.cnblogs.com/Jame-mei 2 3 4 import os,sys 5 6 7 def numif(number_input): # 判斷輸入是否爲數字 8 while not number_input.isdigit(): # 輸入不是數字就進入循環 9 number_input = input('\033[31m 輸入%s不是數字,請從新輸入!\033[0m' % number_input) # 提示從新輸入 10 number = number_input 11 return number 12 13 14 def show_list(file): # 查詢顯示並將文本生成程序須要的字典和列表 15 backend_list = [] 16 backend_all_dict = {} 17 backend_dict = {} 18 server_list = [] 19 with open(file,'r') as f: # 讀取haproxy文件 20 for line in f: 21 22 line = line.strip() 23 if line.startswith('backend') == True: # 判斷是不是backend開頭,讀取backend信息寫到backend_list中 24 backend_name = line.split()[1] 25 backend_list.append(backend_name) # 將文件中backend加到列表中 26 server_list = [] # 清空server_list裏的記錄,遇到新backend能夠輸入新的server_list 27 28 elif line.startswith('server') == True: # 判斷是不是server開頭,讀取server信息寫到backend_all_dict中 29 backend_dict['name'] = line.split()[1] # 讀取文件中server的name 30 backend_dict['IP'] = line.split()[2] # 讀取文件中server的IP 31 backend_dict['weight'] = line.split()[4] # 讀取文件中server的weight 32 backend_dict['maxconn'] = line.split()[6] # 讀取文件中server的maxconn 33 server_list.append(backend_dict.copy()) # 將backend中的信息加到server_list中,此處須要用copy 34 backend_all_dict[backend_name] = server_list # 將server信息對應backend存到字典中 35 36 return (backend_list,backend_all_dict) # 返回backend和server信息 37 38 39 def backend_show(backend_list): # 展現backend列表內容 40 backend_show_dict = {} 41 print("-------------------------------------------------") 42 print("\t\t\t歡迎來到HAproxy文件配置平臺") 43 print("-------------------------------------------------") 44 print("backend列表信息以下:") 45 for k,v in enumerate(backend_list,1): # 逐行讀取backend信息並展現 46 print(k, v) 47 backend_show_dict[str(k)] = v 48 return backend_show_dict # 返回backend和對應編號 49 50 51 def server_show(backend_input,backend_all_dict): # 展現backend下server內容 52 server_show_dict = {} 53 server_list = backend_all_dict[backend_input] 54 for k,v in enumerate(server_list,1): # 編號展現server信息 55 print(k,"name:",v['name'],"\tIP:",v['IP'],"\tweight:",v['weight'],"\tmaxconn:",v['maxconn']) 56 server_show_dict[k] = v 57 return server_show_dict # 返回編號對應的server字典 58 59 60 def action_list(): # 顯示操做列表和編號,並返回操做編號 61 print("-------------------------------------------------") 62 print("操做清單以下:") 63 print(''' 64 1.查詢backend和server信息 65 2.添加backend和server信息 66 3.修改backend和server信息 67 4.刪除backend和server信息 68 5.退出 69 ''') 70 print("-------------------------------------------------") 71 action_num = numif(input("請輸入須要操做的編號:(請輸入數字)")) 72 return action_num 73 74 75 def inquiry(inquiry_input): # 定義查詢功能 76 while True: 77 if inquiry_input in backend_show_dict: # 編號輸入分支 78 backend_input = backend_show_dict[inquiry_input] # 輸入編號獲得backend 79 print(backend_input, ":") 80 server_show(backend_input, backend_all_dict) # 調用server_show,展現backend下server 81 break 82 83 elif inquiry_input in backend_show_dict.values(): # backend名稱輸入分支 84 print(inquiry_input, ":") 85 server_show(inquiry_input, backend_all_dict) # 調用server_show,展現backend下server 86 break 87 88 else: # 校驗異常輸入 89 inquiry_input = input("輸入錯誤,請從新輸入:") 90 91 92 def add(add_input,file): # 定義添加功能 93 (backend_list, backend_all_dict) = show_list(file) 94 while True: 95 if add_input in backend_show_dict: #添加原有backend下server 96 add_dict = {} 97 add_dict['name'] = input("請輸入需增長server名稱:") 98 add_dict['IP'] = input("請輸入需增長IP地址:") 99 add_dict['weight'] = input("請輸入需增長weight值:") 100 add_dict['maxconn'] = input("請輸入需增長maxcoon值:") 101 backend_name_add = backend_list[int(add_input)-1] 102 103 for dict in backend_all_dict[backend_name_add]: # 實現IP已存在,更新weight信息和maxconn信息 104 if add_dict['IP'] in dict.values(): 105 dict['weight'] = add_dict['weight'] 106 dict['maxconn'] = add_dict['maxconn'] 107 break 108 109 else: # IP不存在,就將server增長到backend下 110 backend_all_dict[backend_name_add].append(add_dict) 111 112 backup(file,backend_name_add,backend_all_dict) # 調用backup函數,將新增內容讀寫到文件中 113 print('''name:%s IP:%s weight:%s maxconn:%s已添加成功'''%( 114 add_dict['name'],add_dict['IP'],add_dict['weight'],add_dict['maxconn'])) # 提示添加成功 115 break 116 117 else: # 添加新backend下的server 118 add_dict = {} 119 add_dict['name'] = input("請輸入%s下新增server名稱:"%add_input) 120 add_dict['IP'] = input("請輸入%s下新增IP地址:"%add_input) 121 add_dict['weight'] = input("請輸入%s下新增weight值:"%add_input) 122 add_dict['maxconn'] = input("請輸入%s下新增maxcoon值:"%add_input) 123 backend_name_add = add_input 124 backend_all_dict[backend_name_add] = add_dict # 將新增backend和對應server存到字典中 125 126 file_new = "%s_new" % file # 新建一個文件,用來新增數據 127 with open(file, 'r') as f_read, open(file_new, 'a+') as f_write: # 讀取file文件,追加backend信息 128 for line in f_read: 129 f_write.write(line) 130 f_write.write("\nbackend %s" % backend_name_add) # 追加backend信息 131 server_line_write = '\n\t\tserver {name} {IP} weight {weight} maxconn {maxconn}\n' # 追加server信息 132 f_write.write(server_line_write.format(**add_dict)) # 格式化輸出 133 134 os.system('mv %s %s_backup' % (file, file)) # 將file文件名改成file_backup 135 os.system('mv %s %s' % (file_new, file)) # 將file_new文件名改成file,實現備份 136 print("\nbackend %s" % backend_name_add) 137 print('''name:%s IP:%s weight:%s maxconn:%s已添加成功''' % ( 138 add_dict['name'], add_dict['IP'], add_dict['weight'], add_dict['maxconn'])) # 提示添加成功 139 break 140 141 142 def revise(revise_input): # 定義修改功能 143 revise_dict = {} 144 if revise_input in backend_show_dict: # 判斷輸入是否存在 145 backend_revise = backend_show_dict[revise_input] # 經過編號獲取backend 146 revise_choise = input("是否須要修改該backend名稱:%s;確認請按'y',按任意鍵繼續:"%backend_revise) # 確認是否修改backend名,輸入y修改,不然繼續修改 147 if revise_choise == 'y': 148 backend_revise_new = input("請輸入修改後的backend名:") # 修改backend名 149 backend_all_dict[backend_revise_new] = backend_all_dict.pop(backend_revise) # 將舊backend的server對應到修改後的backend上 150 revise_choise_server = input("是否須要繼續修改%s下的server:確認請按'y',按任意鍵繼續:"%backend_revise_new) # 詢問是否繼續修改 151 if revise_choise_server == 'y': # 繼續修改server 152 server_revise_dict = server_show(backend_revise_new, backend_all_dict) # 展現server信息 153 server_revise_num = numif(input("請輸入須要修改的server編號:")) # 獲取須要修改的server編號 154 revise_dict['name'] = input("請輸入修改後的name:") 155 revise_dict['IP'] = input("請輸入修改後的IP:") 156 revise_dict['weight'] = input("請輸入修改後的weight:") 157 revise_dict['maxconn'] = input("請輸入修改後的maxconn:") 158 server_revise_dict[int(server_revise_num)] = revise_dict # 經過編號修改server信息 159 server_revise_dict_backup = {} 160 server_revise_dict_backup[backend_revise_new] = server_revise_dict.values() # 將修改的server信息對應到修改後的backend存到字典中 161 backup(file, backend_revise, server_revise_dict_backup,backend_revise_new) # 調用backup函數,操做文件 162 163 else: # 不修改server,只修改了backend 164 backup(file, backend_revise, backend_all_dict,backend_revise_new) 165 else: # 未修改backend名狀況時修改server信息 166 server_revise_dict = server_show(backend_revise, backend_all_dict) 167 server_revise_num = numif(input("請輸入須要修改的server編號:")) # 獲取需修改的server編號 168 revise_dict['name'] = input("請輸入修改後的name:") 169 revise_dict['IP'] = input("請輸入修改後的IP:") 170 revise_dict['weight'] = input("請輸入修改後的weight:") 171 revise_dict['maxconn'] = input("請輸入修改後的maxconn:") 172 server_revise_dict[int(server_revise_num)] = revise_dict # 修改的server信息對應到編號中存到字典中 173 server_revise_dict_backup = {} 174 server_revise_dict_backup[backend_revise] = server_revise_dict.values() # 將修改後的server信息對應backend存到字典中 175 backup(file,backend_revise,server_revise_dict_backup) # 調用backup函數,操做文件 176 else: # 輸入錯誤提示從新輸入 177 revise_input_return = input("需修改backend不存在,請從新輸入:") 178 revise(revise_input_return) 179 180 181 def delete(delete_input): # 定義刪除功能 182 if delete_input in backend_show_dict: 183 backend_delete = backend_show_dict[delete_input] 184 delete_choise = input("是否須要刪除該backend:%s;確認請按'y',按任意鍵繼續:"%backend_delete) 185 if delete_choise == 'y': # 判斷是否刪除backend信息 186 del backend_all_dict[backend_delete] # 在backend與server總字典中刪除backend 187 backup(file, backend_delete, backend_all_dict) # 調用backup函數,操做文件 188 189 else: # 刪除server 190 server_delete_dict = server_show(backend_delete, backend_all_dict) 191 server_delete_num = int(numif(input("請輸入須要刪除的server編號:"))) # 除判斷是否時數字外,還需轉換爲整數型 192 while True: # 刪除backend下的server循環 193 if server_delete_num in server_delete_dict: # 判斷輸入編號是否存在 194 server_delete_dict.pop(server_delete_num) 195 server_delete_dict_backup = {} 196 server_delete_dict_backup[backend_delete] = server_delete_dict.values() 197 backup(file, backend_delete, server_delete_dict_backup) # 調用backup函數,操做文件 198 break 199 else: 200 server_delete_num = input("輸入編號不存在,請從新輸入:") # 提示輸入錯誤 201 202 203 def backup(file,backend_name_action,backend_backup_dict,*backend_name_revise): # 定義文檔備份與回寫功能 204 file_new = "%s_new"%file 205 add_flag = False # 爲跳過原backend下server存在 206 with open(file,'r') as f_read , open(file_new,'w+') as f_write: # 同時打開讀文件和寫文件 207 for line in f_read: # 讀取每行信息 208 backend_name = "backend %s" % backend_name_action 209 backend_name_revise = "".join(tuple(backend_name_revise)) # 修改功能會傳參,將元組轉換爲字符串 210 if line.strip() == backend_name: # 讀取某行中有參數中的backend 211 if backend_name_action not in backend_backup_dict and backend_name_revise not in backend_backup_dict: # 爲了刪除backend而存在 212 add_flag = True 213 pass 214 215 elif backend_name_revise in backend_backup_dict: # 判斷修改功能中修改後backend存在與字典中 216 line_revise = "backend %s\n" % backend_name_revise 217 f_write.write(line_revise) 218 for add_dict in backend_backup_dict[backend_name_revise]: # 逐行讀取修改backend下的server信息 219 server_line_write = '\t\tserver {name} {IP} weight {weight} maxconn {maxconn}\n' 220 f_write.write(server_line_write.format(**add_dict)) # 格式化輸出 221 add_flag = True 222 223 else: 224 f_write.write(line) # 將此行寫在文件中 225 for add_dict in backend_backup_dict[backend_name_action]: # 讀取該backend下全部server信息 226 server_line_write = '\t\tserver {name} {IP} weight {weight} maxconn {maxconn}\n' 227 f_write.write(server_line_write.format(**add_dict)) 228 add_flag = True 229 230 elif line.strip().startswith("server") == True and add_flag == True: # 爲了跳過原backend下的server 231 pass 232 233 else: # 寫無用行 234 f_write.write(line) 235 add_flag = False # 寫下無用行後能夠繼續循環 236 237 os.system('mv %s %s_backup' % (file, file)) 238 os.system('mv %s %s' % (file_new, file)) 239 240 241 def backend_exit(): #定義退出功能 242 flag_exit = True 243 b_input = input("操做完畢退出請按'b':") 244 while flag_exit: 245 if b_input == 'b': 246 flag_exit = False 247 return flag_exit 248 249 else: 250 return backend_exit() #使用尾遞歸優化,加上return幫助直接退出,而不須要遞歸一層層退出 251 252 253 flag = True # 主函數開始 254 while flag: 255 flag_main = True 256 flag_action = True 257 file = 'haproxy' # 文件名賦值 258 (backend_list, backend_all_dict) = show_list(file) # 調用show_list函數獲取backend和server信息 259 backend_show_dict = backend_show(backend_list) # 展現backend信息 260 action_num = action_list() # 展現功能項,並輸入操做編號 261 while flag_main: 262 if action_num == '1': 263 inquiry(input("請輸入須要查詢的backend編號或名稱:")) 264 flag_main = backend_exit() 265 break 266 267 if action_num == '2': 268 add(input("請輸入須要添加的現有backend編號或新backend名稱:"), file) 269 flag_main = backend_exit() 270 break 271 272 if action_num == '3': 273 revise(input("請輸入須要修改的backend編號或名稱:")) 274 flag_main = backend_exit() 275 break 276 277 if action_num == '4': 278 delete(input("請輸入須要刪除的backend編號或名稱:")) 279 flag_main = backend_exit() 280 break 281 282 if action_num == '5': 283 sys.exit() 284 285 elif action_num not in range(5): # 當輸入不在編號中,提示並從新輸入 286 print("\033[31;1m輸入錯誤請從新輸入!\033[0m") 287 flag_main = False
1.字符編碼與轉碼
詳細文章:
http://www.cnblogs.com/linhaifeng/articles/5950339.html 林海峯老師
http://www.cnblogs.com/yuanchenqi/articles/5956943.html(中文博客整理)
http://www.diveintopython3.net/strings.html(英文文檔)
需知:
1.在python2默認編碼是ASCII, python3裏默認是unicode
2.unicode 分爲 utf-32(佔4個字節),utf-16(佔兩個字節),utf-8(佔1-4個字節), so utf-16就是如今最經常使用的unicode版本, 不過在文件裏存的仍是utf-8,由於utf8省空間
3.在py3中encode,在轉碼的同時還會把string 變成bytes類型,decode在解碼的同時還會把bytes變回string
GBK-->UTF-8的轉換,依靠unicode來進行(以下圖,是適合py2.x,學Py3的也能夠做爲了解!):
2.字符編碼與轉碼的實例
1):基於py2.7:
1 #Author:http://www.cnblogs.com/Jame-mei 2 #-*-coding:utf-8-*- 3 #注意,基於py2.7必需要加utf-8的解釋器 4 5 import sys 6 7 print (sys.getdefaultencoding()) 8 9 ''' 10 #1.utf-8 轉換成gbk 11 s = '您好' 12 s_to_unicode=s.decode('utf-8') 13 print (s_to_unicode) 14 s_to_gbk=s_to_unicode.encode("gbk") 15 print (s_to_gbk)#這個在linux終端顯示上調整爲gbk,才能顯示。 16 17 18 #2.gbk轉換成utf-8 19 gbk_to_utf8=s_to_gbk.decode("gbk").encode("utf-8") 20 print(gbk_to_utf8) 21 22 ''' 23 24 ''' 25 #簡易版:utf-8轉出成gbk 26 #utf-8是unicode的擴展集,是能夠直接打印的,gbk和unicode必需要通過轉換才行。 27 s=u'您好' #將utf-8直接轉換成unicode編碼! 28 print(s) 29 s_to_gbk=s.encode("gbk") 30 print (s_to_gbk)#這個在linux終端顯示上調整爲gbk,才能顯示。 31 32 33 #2.gbk轉換成utf-8 34 gbk_to_utf8=s_to_gbk.decode("gbk").encode("utf-8") 35 print(gbk_to_utf8) 36 ''' 37 38 39 40 #3.utf-8轉換成gb2312 41 s="您好" 42 s_gb2312=s.decode("utf-8").encode("gb2312") 43 print (s_gb2312) 44 45 #4.gb2312轉換成gbk 46 gb2312_to_gbk=s_gb2312.decode("gb2312").encode("gbk") 47 print (gb2312_to_gbk) 48 49 50 51 #5.utf-8轉換成gbk 52 gb2312_to_utf=s.decode("utf-8").encode("gbk") 53 print (gb2312_to_gbk)
2):基於py3.6:
1 #Author:http://www.cnblogs.com/Jame-mei 2 #-*-coding:utf-8-*- 3 #基於python3.x版本 4 5 import sys 6 print (sys.getdefaultencoding()) 7 8 #1.將utf-8轉換成gbk 9 ''' 10 str="你哈" 11 str_gbk=str.encode("gbk") 12 print (str_gbk) 13 #encode("gbk"):b'\xc4\xe3\xb9\xfe' 14 #encode()爲默認utf-8:b'\xe4\xbd\xa0\xe5\x93\x88' 15 16 17 2.將gbk轉成utf-8 18 gbk_to_utf8=str_gbk.decode("gbk").encode("utf-8") 19 print (gbk_to_utf8) 20 ''' 21 22 #3.py3.x中將utf-8轉換成gb2312 23 s="我愛北京天安門" 24 s_gb2312=s.encode("gb2312") #默認就是unicode,不用再decode,喜大普奔 25 print (s_gb2312) 26 27 #4.而後將gb2312轉換成utf-8 28 gb2312_to_unicode=s_gb2312.decode("gb2312") 29 print (gb2312_to_unicode) 30 31 unicode_to_utf8=s_gb2312.decode("gb2312").encode("utf-8") 32 print (unicode_to_utf8) 33 34 ''' 35 總結: 36 python3.x默認爲2種數據類型:默認unicode和bytes類型,其中utf-8爲unicode的擴展,因此utf-8能夠直接encode("gbk")轉換成gbk 37 可是gbk不能直接轉換成utf-8,須要decode("gbk")再encode("utf-8")才行。 38 39 python3中,將unicode轉換成gbk,utf8,gb2312類型的時候,同時顯示爲bytes類型。 40 ''' 41 42 43 ''' 44 思考區: 45 str="你哈" #這裏python默認數據類型爲unicode編碼,coding:gbk只是修改了文件的編碼方式。 46 print (str.encode('gbk')) 47 print (str.encode('utf-8')) 48 print (str.encode('utf-8').decode('utf-8').encode('gb2312')) #轉換成gb2312,與gbk的bytes結果同樣,是由於gbk向下兼容gb2312! 49 50 51 52 '''
3.若是對編碼格式仍是迷茫,請看看alex的雞湯文:
1)先說python2:
2)再說python3:
編碼應用比較多的場景應該是爬蟲了,互聯網上不少網站用的編碼格式很雜,雖然總體趨向都變成utf-8,但如今仍是很雜,因此爬網頁時就須要你進行各類編碼的轉換,不過生活正在變美好,期待一個不須要轉碼的世界。
最後,編碼is a piece of fucking shit, noboby likes it.
1.函數基本語法及特性
函數一詞來源於數學,但編程中的「函數」概念,與數學中的函數是有很大不一樣的,具體區別,咱們後面會講,編程中的函數在英文中也有不少不一樣的叫法。在BASIC中叫作subroutine(子過程或子程序),在Pascal中叫作procedure(過程)和function,在C中只有function,在Java裏面叫作method。
特性:
1
2
3
4
|
def sayhi(): #函數名
print ( "Hello, I'm nobody!" )
sayhi() #調用函數
|
能夠帶參數:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#下面這段代碼
a,b = 5 , 8
c = a * * b
print (c)
#改爲用函數寫
def calc(x,y):
res = x * * y
return res #返回函數執行結果
c = calc(a,b) #結果賦值給c變量
print (c)
|
2.函數的應用場景:
1 #Author:http://www.cnblogs.com/Jame-mei 2 3 def func1(): 4 '''定義一個函數:test1''' 5 print ('in the func1') 6 return 0 7 8 9 def fun2(): 10 '''定義一個過程(沒有返回值的函數!):test2''' 11 print ('in the func2') 12 13 14 15 x=func1() 16 17 y=fun2() 18 19 print ('func1 return is %s' %x) 20 #print('func1 return is {_x}'.format(_x=x)) 與%s輸出相同 21 #func1 return is 0 22 23 print ('func2 return is {_y}'.format(_y=y)) 24 #func2 return is None
1 #Author:http://www.cnblogs.com/Jame-mei 2 import time 3 4 def logger(): 5 #time_format='%Y-%m-%d %X' ===>%F %X 6 time_format='%F %X' 7 time_current=time.strftime(time_format) 8 with open('test_def','a+') as f: 9 f.write("%s end action\n" %time_current) #2.可擴展 10 11 def test1(): 12 print ('in the test1') 13 logger() #1.代碼重用,3.一致性等 14 15 def test2(): 16 print ('in the test2') 17 logger() 18 19 def test3(): 20 print ('in the test3') 21 logger() 22 23 24 test1() 25 test2() 26 test3()
1 如今老闆讓你寫一個監控程序,監控服務器的系統情況,當cpu\memory\disk等指標的使用量超過閥值時即發郵件報警,你掏空了全部的知識量,寫出瞭如下代碼 2 3 while True: 4 if cpu利用率 > 90%: 5 #發送郵件提醒 6 鏈接郵箱服務器 7 發送郵件 8 關閉鏈接 9 10 if 硬盤使用空間 > 90%: 11 #發送郵件提醒 12 鏈接郵箱服務器 13 發送郵件 14 關閉鏈接 15 16 if 內存佔用 > 80%: 17 #發送郵件提醒 18 鏈接郵箱服務器 19 發送郵件 20 關閉鏈接 21 上面的代碼實現了功能,但即便是鄰居老王也看出了端倪,老王親切的摸了下你家兒子的臉蛋,說,你這個重複代碼太多了,每次報警都要重寫一段發郵件的代碼,太low了,這樣幹存在2個問題: 22 23 代碼重複過多,一個勁的copy and paste不符合高端程序員的氣質 24 若是往後須要修改發郵件的這段代碼,好比加入羣發功能,那你就須要在全部用到這段代碼的地方都修改一遍 25 你以爲老王說的對,你也不想寫重複代碼,但又不知道怎麼搞,老王好像看出了你的心思,此時他抱起你兒子,笑着說,其實很簡單,只須要把重複的代碼提取出來,放在一個公共的地方,起個名字,之後誰想用這段代碼,就經過這個名字調用就好了,以下 26 27 28 def 發送郵件(內容) 29 #發送郵件提醒 30 鏈接郵箱服務器 31 發送郵件 32 關閉鏈接 33 34 while True: 35 36 if cpu利用率 > 90%: 37 發送郵件('CPU報警') 38 39 if 硬盤使用空間 > 90%: 40 發送郵件('硬盤報警') 41 42 if 內存佔用 > 80%: 43 發送郵件('內存報警') 44 45 46 你看着老王寫的代碼,氣勢恢宏、磅礴大氣,代碼裏透露着一股內斂的傲氣,心想,老王這我的真是不通常,忽然對他的背景更感興趣了,問老王,這些花式玩法你都是怎麼知道的? 老王親了一口你兒子,捋了捋不存在的鬍子,淡淡的講,「老夫,年少時,師從京西沙河淫魔銀角大王 」, 你一聽「銀角大王」這幾個字,不禁的嬌軀一震,心想,真nb,怪不得代碼寫的這麼6, 這「銀角大王」當年在江湖上但是數得着的響噹噹的名字,只惋惜後期縱慾過分,卒於公元2016年, 真是惋惜了,只留下其哥哥孤守當年兄弟倆一塊兒打下來的江山。 此時你看着的老王離開的身影,感受你兒子跟他愈來愈像了。。。
1 #Author:http://www.cnblogs.com/Jame-mei 2 #註釋:函數的返回值的實例 3 4 def test1(): 5 print ('in the test1') 6 #output:in the test1,下面的print就不輸出了,由於遇到了return 7 return 0 8 #print ('in the test2') 9 10 11 def test2(): 12 print ('in the test2') 13 return test3() #把test3()函數做爲返回值,也叫高階函數! 14 15 def test3(): 16 print ('in the test3') 17 return 1,'hello',['alex','jame','oldboy'],{'alex':28,'oldboy':45,'jame':27},(2,3,4,5) 18 19 def test4(): 20 print ('in the test4') 21 22 23 x=test1() 24 y=test2() 25 z=test3() 26 m=test4() 27 28 print (x) 29 #0 30 31 print (y) 32 ##(1, 'hello', ['alex', 'jame', 'oldboy'], {'alex': 28, 'oldboy': 45, 'jame': 27}, (2, 3, 4, 5)) 33 34 print (z)#把字符串,數字,列表,字典,元祖都返回到一個元祖裏。 35 #(1, 'hello', ['alex', 'jame', 'oldboy'], {'alex': 28, 'oldboy': 45, 'jame': 27}, (2, 3, 4, 5)) 36 37 38 print (m) #沒有return,則返回None 39 40 函數的返回值
總結:
1).不一樣返回值類型
*函數中沒有return ,返回None。
*函數中 return 返回中只有1個變量時候,爲返回值爲object對象。
例如return (2),return [2],return 'hello'分別返回是2,[2],hello單個元素。
*函數中 return 返回中有多個變量時候,會把多個變量包含在一個元祖中,返回一個元祖!
例如 return (2,) ,返回的一個元祖(2,) return 2,'hello',(2,3,4) ,返回(2, 'hello', (2, 3, 4)) 元祖。
*函數中 return另一個函數test3(),則返回只test3()的返回值
(2, 'hello', (2, 3, 4))
2).函數爲何要返回值?
爲後面的程序調用,經過返回值的來進行判斷,從而完成相關代碼的邏輯。
形參變量只有在被調用時才分配內存單元,在調用結束時,即刻釋放所分配的內存單元。所以,形參只在函數內部有效。函數調用結束返回主調用函數後則不能再使用該形參變量。
實參能夠是常量、變量、表達式、函數等,不管實參是何種類型的量,在進行函數調用時,它們都必須有肯定的值,以便把這些值傳送給形參。所以應預先用賦值,輸入等辦法使參數得到肯定值。
形參和實參的區別:形參是虛擬的,不佔用內存,形參變量只有在被調用的時候才分配內存。實參是一個變量,佔用內存空間,數據傳送單向,實參傳給形參,形參不能傳給實參!
1):默認參數
默認參數的特色:調用函數時候,默認參數非必須傳(能夠默認不寫,也能夠用位置參數從新賦值,也能夠在最後用關鍵字從新賦值)
默認參數的用途:1.默認安裝參數 2.默認端口參數等等預設的默認。
1 1默認參數 2 def stu_register01(name, age, country, course): 3 print("----註冊學生信息------") 4 print("姓名:", name) 5 print("age:", age) 6 print("國籍:", country) 7 print("課程:", course) 8 9 stu_register01("王山炮", 22, "CN", "python_devops") 10 stu_register01("張叫春", 21, "CN", "linux") 11 12 output: 13 ----註冊學生信息------ 14 姓名: 王山炮 15 age: 22 16 國籍: CN 17 課程: python_devops 18 ----註冊學生信息------ 19 姓名: 張叫春 20 age: 21 21 國籍: CN 22 課程: linux 23 24 25 26 #===================>改造爲默認參數調用,默認參數必須放在最後,調用的時候也須要按照順序。 27 def stu_register02(name, age,course,country="CN"): 28 print("----註冊學生信息------") 29 print("姓名:", name) 30 print("age:", age) 31 print("國籍:", country) 32 print("課程:", course) 33 34 stu_register02("張叫春", 21, "CN", "linux") #邏輯錯誤,默認值會被課程覆蓋,順序很重要。 35 stu_register02("金妍希", 21,"舞蹈") #不填寫國籍,默認中國 36 stu_register02("Tom", 22,"python_devops",country="US") #修改默認國籍 37 38 output: 39 ----註冊學生信息------ 40 姓名: 張叫春 41 age: 21 42 國籍: linux 43 課程: CN #這裏會被覆蓋!! 44 ----註冊學生信息------ 45 姓名: 金妍希 46 age: 21 47 國籍: CN 48 課程: 舞蹈 49 ----註冊學生信息------ 50 姓名: Tom 51 age: 22 52 國籍: US 53 課程: python_devops
2):位置參數 和 3)關鍵字參數
1 def test(x,y): 2 print (x) 3 print (y) 4 5 6 #1.位置參數調用(與形參順序一一對應!) 7 test(1,2) 8 9 #2.關鍵字參數調用(與形參順序無關,與關鍵字對應!) 10 test(y=3,x=4) 11 12 #3.既有位置參數又有關鍵字參數,以位置參數優先!! 13 #3.1.關鍵字+位置參數(執行錯誤,第一個爲關鍵字參數調用,第二個參數也應該是關鍵字才行!) 14 test(x=1,4) 15 16 17 #3.2.位置參數+關鍵字混用 18 test(3,y=5) #(執行正確,第一個參數與位置相關,第二個必需要位置參數的值,或者關鍵參數y=...) 19 #test(3,x=4) #(執行錯誤,第一個參數與位置相關,關鍵參數應該順序是y=...) 20 21 22 23 #4.大於2個位置參數和關鍵參數的混用狀況,關鍵參數不能寫在位置參數前面的! 24 def test2(x,y,z): 25 print (x,y,z) 26 27 #test2(3,y=2,6) #執行錯誤,關鍵字參數應該放在位置參數後面. 28 #test2(1,2,x=3) #執行錯誤,最後一個只能是z. 29 test2(1,2,z=3) #執行正確,最後一個參數對應爲z 30 test2(1,z=3,y=2) #執行正確,後面兩個都爲關鍵字參數與順序無關 31 32 33 34 #以上實例多練習體會其中的原理!不一一帖出來了。
4):參數組(非固定參數)
1): *args :把N個參數轉換成元祖的方式,其中*args接受N個位置參數!
1 def test3(*args): #*args也能夠自定義爲 *jame 2 print(args) 3 4 test3(1,2,3,4,5) #獲得一個元祖(1,2,3,4,5) 5 6 test3(*['a','b']) #至關於*args=*['a','b'],獲得('a', 'b') 7 8 test3(['x','y','z'],['1','2','3']) 9 #至關於args=tunple(['x','y','z']),獲得(['x', 'y', 'z'],) 10 #當爲2個列表時候,獲得, (['x','y','z'],['1', '2', '3']) 11 12 13 14 #x位置參數不能放在 *args後面!! 15 def test4(x,*args): 16 print (x) 17 print (args) 18 19 test4(1,'a','b',2,3,4) 20 ''' 21 output: 22 1 23 ('a', 'b', 2, 3, 4) 24 '''
2): **kwargs:把N個參數轉換成字典的方式,其中**kwargs接受N個關鍵字參數!
1 def test4(**kwargs): 2 print (kwargs) 3 print(kwargs['name']) #輸出字典的key-value! 4 print (kwargs['age']) 5 print (kwargs['sex']) 6 7 8 #方式1 9 test4(name='jame',age='27',sex='男',address='Shanghai') 10 ''' 11 output: 12 輸出一個字典 13 {'name': 'jame', 'age': '27', 'sex': '男', 'address': 'Shanghai'} 14 jame 15 27 16 男 17 ''' 18 19 #方式2 20 test4(**{'name':'tom','age':8,'sex':'女'}) #**{}==**kwargs 21 ''' 22 output: 23 {'name': 'tom', 'age': 8} 24 tom 25 8 26 女 27 '''
3): **kwargs與位置參數混用,**kwargs放在位置參數的後面。
1 def test5(name,**kwargs): 2 print (name) 3 print (kwargs) 4 5 #1.只填寫位置參數name,**kwargs省略輸出一個控的字典 6 test5('Jack') 7 ''' 8 output: 9 Jack 10 {} 11 ''' 12 13 14 #2.位置參數和**kwargs都填寫,注意age,sex不帶''/"",不要跟字典搞混淆了。 15 test5('kater',age=18,sex='boy') 16 17 ''' 18 output: 19 kater 20 {'age': 18, 'sex': 'boy'} 21 22 ''' 23 24 25 #3.位置參數和**kwargs做爲一個字典的方式和2.結果同樣,感受更加清晰! 26 27 test5('Alice',**{'age':16,'sex':'girl'}) 28 ''' 29 output: 30 Alice 31 {'age': 16, 'sex': 'girl'} 32 '''
4):順序參數,默認參數和**kwargs混用(優先級:順序參數>默認參數>**kwargs關鍵字參數)
1 def test06(name,**kwargs,age=18): #報錯,age=18默認參數不能放在最後,參數組(關鍵字參數)必定要日後放! 2 3 def test06(name,age=18,**kwargs): 4 print(name,age,kwargs) 5 6 7 test06('python',20,sex='unknow',address='US') #age爲默認值能夠不寫,也能夠寫20,爲了易讀性最好寫age=30等等 8 ''' 9 output: 10 python 11 20 12 {'sex': 'unknow', 'address': 'US'} 13 ''' 14 15 16 #test06('python',20,sex='unknow',address='US',age=38) 17 # #前面若是給默認值賦值了,再**kwargs中指定關鍵字age則報錯!!儘可能不要這麼寫,容易歧義混亂! 18 19 20 test06('python',sex='unknow',address='US',age=38) #不寫age,在**kwargs後面參數中又指定了age=38,最後替代默認值20 21 ''' 22 output: 23 python 38 {'sex': 'unknow', 'address': 'US'} 24 25 '''
5):順序參數,默認值參數,*args , **kwargs混用( 優先級: 順序參數 > 默認值參數 > *args(接受位置參數) > **kwargs(接受關鍵字參數) )
1 def test07 (name,age=18,*args,**kwargs): 2 print (name) 3 print (age) 4 print (args) 5 print (kwargs) 6 7 8 test07('dog',20,sex='unknow',address='doghome') 9 ''' 10 輸出: 11 dog 12 20 13 () #由於*args接受的是位置參數,不能是關鍵字參數,因此爲空! 14 {'sex': 'unknow', 'address': 'doghome'} 15 ''' 16 17 test07('cat',9,1,2,3,sex='catgirl',adress='cathome') 18 ''' 19 輸出: 20 cat 21 9 22 (1, 2, 3) 23 {'sex': 'catgirl', 'adress': 'cathome'} 24 '''
函數是Python內建支持的一種封裝,咱們經過把大段代碼拆成函數,經過一層一層的函數調用,就能夠把複雜任務分解成簡單的任務,這種分解能夠稱之爲面向過程的程序設計。函數就是面向過程的程序設計的基本單元。
函數式編程中的函數這個術語不是指計算機中的函數(其實是Subroutine),而是指數學中的函數,即自變量的映射。也就是說一個函數的值僅決定於函數參數的值,不依賴其餘狀態。好比sqrt(x)函數計算x的平方根,只要x不變,不論何時調用,調用幾回,值都是不變的。
Python對函數式編程提供部分支持。因爲Python容許使用變量,所以,Python不是純函數式編程語言。
簡單說,"函數式編程"是一種"編程範式"(programming paradigm),也就是如何編寫程序的方法論。
主要思想是把運算過程儘可能寫成一系列嵌套的函數調用。舉例來講,如今有這樣一個數學表達式:
(1 + 2) * 3 - 4
傳統的過程式編程,可能這樣寫:
var a = 1 + 2;
var b = a * 3;
var c = b - 4;
函數式編程要求使用函數,咱們能夠把運算過程定義爲不一樣的函數,而後寫成下面這樣:
var result = subtract(multiply(add(1,2), 3), 4);
這段代碼再演進如下,能夠變成這樣
add(1,2).multiply(3).subtract(4)
這基本就是天然語言的表達了。再看下面的代碼,你們應該一眼就能明白它的意思吧:
merge([1,2],[3,4]).sort().search("2")
所以,函數式編程的代碼更容易理解。
要想學好函數式編程,不要玩py,玩Erlang,Haskell,
在子程序中定義的變量稱爲局部變量,在程序的一開始定義的變量稱爲全局變量。
1 #Author:http://www.cnblogs.com/Jame-mei 2 3 school='oldboy linux' #定義全局變量 4 5 #局部變量和全局變量 6 def change_name(name): 7 global school #強制聲明修改全局變量! 8 school='Mage linux' 9 print ('Before change',name,school) 10 name='Alex Li' #局部變量,做用域在函數內部生效。 11 print ('After change',name) 12 age=12 13 14 15 name='Jame' 16 change_name(name) 17 print (name) #依然是Jame,沒有發生變化。 18 #print (age) #NameError: name 'age' is not defined,局部變量做用域只在函數change_name中。 19 20 print ('global school:',school) #全局變量由oldboy linux--->mage linux
實例2:編程規範 禁止在函數內部修改/定義 global 全局變量!
1 def change_name(): 2 global name 3 name='Jame-mei' 4 5 6 change_name() 7 print (name) 8 輸出: 9 Jame-mei
實例3:編程規範 禁止修改global全局變量(單獨的字符串和整數),列表、字典、集合、類等複雜數據類型能夠修改。
1 names=['Alex','oldboy','mage'] 2 def change_name(): 3 names[0]='金角大王' 4 print (names) 5 6 7 change_name() #全局變量 8 9 10 #字符串,整數不能夠修改,其餘的能夠修改! 11 #列表,字典,集合,類等能夠修改。
在函數內部,能夠調用其餘函數。若是一個函數在內部調用自身自己,這個函數就是遞歸函數。
函數遞歸調用,在調用一個函數的過程當中又直接或間接地調用了本身稱之爲函數的遞歸調用
本質就是一個重複的過程,必須有兩個明確的階段
#一、回溯:一層一層地遞歸調用下去,沒進入下一層問題的規模都應該有所減小
#二、遞推:遞歸必需要有一個明確的結束條件,在知足該條件的狀況下會終止遞歸,
往回一層一層地結束調用
遞歸特性:
1. 必須有一個明確的結束條件。
2. 每次進入更深一層遞歸時,問題規模相比上次遞歸都應有所減小。
3. 遞歸效率不高,遞歸層次過多會致使棧溢出(在計算機中,函數調用是經過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。因爲棧的大小不是無限的,因此,遞歸調用的次數過多,會致使棧溢出)
堆棧掃盲http://www.cnblogs.com/lln7777/archive/2012/03/14/2396164.html
實例1:棧內存溢出實例保護機制
1 def calc(n): 2 print (n) 3 return calc(n+1) 4 5 6 calc(1) 7 8 輸出: 9 991 10 992 11 993 12 994 13 995 14 996 15 997 16 998Traceback (most recent call last): 17 File "E:/pythonwork/s14/day03/def_digui.py", line 11, in <module> 18 calc(1) 19 File "E:/pythonwork/s14/day03/def_digui.py", line 7, in calc 20 return calc(n+1) 21 File "E:/pythonwork/s14/day03/def_digui.py", line 7, in calc 22 return calc(n+1) 23 File "E:/pythonwork/s14/day03/def_digui.py", line 7, in calc 24 return calc(n+1) 25 [Previous line repeated 993 more times] 26 File "E:/pythonwork/s14/day03/def_digui.py", line 6, in calc 27 print (n) 28 RecursionError: maximum recursion depth exceeded while calling a Python object
實例2:給遞歸一個結束條件
1 def calc(n): 2 print(n) 3 if int(n/2) >0: 4 return calc(int(n/2)) 5 print (n) 6 7 8 9 calc(10) 10 11 12 輸出: 13 10 14 5 15 2 16 1 17 1 18 19 Process finished with exit code 0
4.遞歸 vs while 循環
遞歸只須要把控住結束或進入遞歸的條件便可,至於循環次數或者嵌套的層數無需考慮。
''' # 直接 # import sys # print(sys.getrecursionlimit()) # sys.setrecursionlimit(10000) # def foo(n): # print('from foo',n) # foo(n+1) # # foo(0) # 間接 # def bar(): # print('from bar') # foo() # # def foo(): # print('from foo') # bar() # # foo() # def foo(): # print('from foo') # foo() # # foo() # age(5) = age(4) + 2 # age(4) = age(3) + 2 # age(3) = age(2) + 2 # age(2) = age(1) + 2 # age(1) = 18 # age(n) = age(n-1) + 2 #n > 1 # age(n) = 18 #n=1 # # def age(n): # if n == 1: # return 18 # return age(n-1) + 2 # # # print(age(5)) # l=[1,[2,[3,[4,[5,[6,[7,[8,[9,]]]]]]]]] # # def tell(l): # for item in l: # if type(item) is list: # #item 是列表 # # 再次調用自己的邏輯,傳入item # tell(item) # else: # #item是單獨的元素 # print(item) # # tell(l) # 數字列表,數字是從小到大排列的 nums=[3,11,13,15,23,27,43,51,72,81,93,101] # 算法:就是如何高效地解決某一個具體問題的方法 # l1=[3,11,13,15,23,27] # l2=[23,27] # l3=[23] def binary_search(nums,find_num): print(nums) if len(nums) == 0: print('not exists') return mid_index=len(nums) // 2 if find_num > nums[mid_index]: # in the right nums=nums[mid_index+1:] # 重複調用自己的邏輯,傳入新的nums binary_search(nums,find_num) elif find_num < nums[mid_index]: # in the left nums=nums[:mid_index] # 重複調用自己的邏輯,傳入新的nums binary_search(nums,find_num) else: print('find it') binary_search(nums,94)
1.高階函數
變量能夠指向函數,函數的參數能接收變量,那麼一個函數就能夠接收另外一個函數做爲參數,這種函數就稱之爲高階函數。
def
add(x,y,f):
return
f(x)
+
f(y)
res
=
add(
3
,
-
6
,
abs
)
print
(res)
2.匿名函數
匿名函數就是不須要顯式的指定函數
1
2
3
4
5
6
7
8
|
#這段代碼
def calc(n):
return n * * n
print (calc( 10 ))
#換成匿名函數
calc = lambda n:n * * n
print (calc( 10 ))
|
你也許會說,用上這個東西沒感受有毛方便呀,若是是這麼用,確實沒毛線改進,不過匿名函數主要是和其它函數搭配使用的呢,以下
1
2
3
|
res = map ( lambda x:x * * 2 ,[ 1 , 5 , 7 , 4 , 8 ])
for i in res:
print (i)
|
輸出:
1
25
49
16
64
3.匿名函數的實例操做
# 有名函數:能夠經過名字重複使用 # def foo(): # print('from foo') # # foo() #匿名函數:臨時用一次之後不會再用了 # def sum2(x,y): # return x + y # print(sum2) # sum2=lambda x,y:x + y # print(sum2) # res=sum2(1,2) # print(res) # 定義匿名函數就是定義出了一個函數的內存 # res=(lambda x,y:x + y)(1,2) # print(res) salaries={ 'egon':300000, 'alex':100000000, 'wupeiqi':10000, 'yuanhao':2000 } # print(max([11,22,33,44])) # print(max(salaries)) # def func(k): # return salaries[k] # print(max(salaries,key=lambda x:salaries[x])) # for k in salaries: # res=func(k) # 將func的返回值當作比較依據 # print(min(salaries,key=lambda x:salaries[x])) # num=[3,1,4,9] # l=sorted(num) # 默認從小到大排 # l=sorted(num,reverse=True) # 從大到小排 # print(l) # salaries={ # 'egon':300, # 'alex':100000000, # 'wupeiqi':10000, # 'yuanhao':2000 # } # 按照薪資高低排序人名 # print(sorted(salaries,key=lambda x:salaries[x])) # 瞭解 # map,reduce,filter # map:映射 names=['alex','lxx','wxx'] # chicken=map(lambda x:x+'_dsb',names) # print(chicken) # print(list(chicken)) # l=[name+'_dsb' for name in names] # print(l) # filter:過濾 # names=['alex_teacher','lxx_teacher','wxx_teacher','egon_boss'] # res=filter(lambda x:x.endswith('teacher'),names) #filter會"for循環"names,取出來每個名字,而後傳給指定的函數,若是函數的返回值爲True,則留下該名字 # for item in res: # print(item) # l=(name for name in names if name.endswith('teacher')) # print(list(l)) # reduce:合併 from functools import reduce l=['a','b','c','d','e'] # res=reduce(lambda x,y:x+y,l,'AAA') # #'AAA' + 'a'='AAAa' #'AAAa' + 'b' = 'AAAab' #'AAAab' + 'c' # print(res) # res=reduce(lambda x,y:x+y,l) #'a','b' # print(res) # res=reduce(lambda x,y:x+y,range(0,101)) # print(res)
固然此表你在文件存儲時能夠這樣表示
1
|
1
,Alex Li,
22
,
13651054608
,IT,
2013
-
04
-
01
|
現須要對這個員工信息文件,實現增刪改查操做
注意:以上需求,要充分使用函數,請盡你的最大限度來減小重複代碼!
代碼地址:https://gitee.com/meijinmeng/Sqltest.git