Python基礎-week03 集合 , 文件操做 和 函數詳解

一.集合及其運算

  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等等
View Code

 

  

   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
View Code

 

 

二.文件讀與寫詳解(1-3)

  *對文件操做流程:編程

    1):打開文件,獲得文件句柄並賦值給一個變量windows

    2):經過句柄對文件進行操做python3.x

    3):關閉文件

  *打開文件的模式有:

  • r,只讀模式(默認)。
  • w,只寫模式。【不可讀;不存在則建立;存在則刪除內容;】
  • a,追加模式。【可讀;   不存在則建立;存在則只追加內容;】

      "+" 表示能夠同時讀寫某個文件:

  • r+,可讀寫文件。【可讀;可寫;可追加】
  • w+,寫讀
  • a+,追加讀寫!

     "U"表示在讀取時,能夠將 \r \n \r\n自動轉換成 \n (與 r 或 r+ 模式同使用)

  • rU
  • r+U

     "b"表示處理二進制文件(如:FTP發送上傳ISO鏡像文件,linux可忽略,windows處理二進制文件時需標註)

  • rb
  • wb
  • ab

  

  

  

 

 

  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 '''
View Code

 

  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 '''
View Code

 

 

 實現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)
View Code

  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 '''
View Code

 

 

 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()
View Code

 

   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()
View Code

 

    程序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
View Code

 

    實現過程:

  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
對haproxy.conf增刪改查

 

  

 

 

四.字符編碼轉化詳解(1-2)

  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)
python2.7

      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 '''
python3.6

 

  3.若是對編碼格式仍是迷茫,請看看alex的雞湯文:

  1)先說python2:

  1. py2裏默認編碼是ascii
  2. 文件開頭那個編碼聲明是告訴解釋這個代碼的程序 以什麼編碼格式 把這段代碼讀入到內存,由於到了內存裏,這段代碼實際上是以bytes二進制格式存的,不過即便是2進制流,也能夠按不一樣的編碼格式轉成2進制流,你懂麼?
  3. 若是在文件頭聲明瞭#_*_coding:utf-8*_,就能夠寫中文了, 不聲明的話,python在處理這段代碼時按ascii,顯然會出錯, 加了這個聲明後,裏面的代碼就全是utf-8格式了
  4. 在有#_*_coding:utf-8*_的狀況下,你在聲明變量若是寫成name=u"大保健",那這個字符就是unicode格式,不加這個u,那你聲明的字符串就是utf-8格式
  5. utf-8 to gbk怎麼轉,utf8先decode成unicode,再encode成gbk

  2)再說python3:

  1. py3裏默認文件編碼就是utf-8,因此能夠直接寫中文,也不須要文件頭聲明編碼了,乾的漂亮
  2. 你聲明的變量默認是unicode編碼,不是utf-8, 由於默認便是unicode了(不像在py2裏,你想直接聲明成unicode還得在變量前加個u), 此時你想轉成gbk的話,直接your_str.encode("gbk")便可以
  3. 但py3裏,你在your_str.encode("gbk")時,感受好像還加了一個動做,就是就是encode的數據變成了bytes裏,我擦,這是怎麼個狀況,由於在py3裏,str and bytes作了明確的區分,你能夠理解爲bytes就是2進制流,你會說,我看到的不是010101這樣的2進制呀, 那是由於python爲了讓你能對數據進行操做而在內存級別又幫你作了一層封裝,不然讓你直接看到一堆2進制,你能看出哪一個字符對應哪段2進制麼?什麼?本身換算,得了吧,你連超過2位數的數字加減運算都費勁,還仍是省省心吧。  
  4. 那你說,在py2裏好像也有bytes呀,是的,不過py2裏的bytes只是對str作了個別名(python2裏的str就是bytes, py3裏的str是unicode),沒有像py3同樣給你顯示的多出來一層封裝,但其實其內部仍是封裝了的。 這麼講吧, 不管是2仍是三, 從硬盤到內存,數據格式都是 010101二進制到-->b'\xe4\xbd\xa0\xe5\xa5\xbd' bytes類型-->按照指定編碼轉成你能看懂的文字

  編碼應用比較多的場景應該是爬蟲了,互聯網上不少網站用的編碼格式很雜,雖然總體趨向都變成utf-8,但如今仍是很雜,因此爬網頁時就須要你進行各類編碼的轉換,不過生活正在變美好,期待一個不須要轉碼的世界。

  最後,編碼is a piece of fucking shit, noboby likes it.

 

 

五.函數與函數式編程(1-2)

  1.函數基本語法及特性

  函數一詞來源於數學,但編程中的「函數」概念,與數學中的函數是有很大不一樣的,具體區別,咱們後面會講,編程中的函數在英文中也有不少不一樣的叫法。在BASIC中叫作subroutine(子過程或子程序),在Pascal中叫作procedure(過程)和function,在C中只有function,在Java裏面叫作method。

  定義: 函數是指將一組語句的集合經過一個名字(函數名)封裝起來,要想執行這個函數,只需調用其函數名便可

  特性:

    1. 減小重複代碼
    2. 使程序變的可擴展
    3. 使程序變得易維護

  語法定義:

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
= a**b
print(c)
 
 
#改爲用函數寫
def calc(x,y):
    res = x**y
    return res #返回函數執行結果
 
= 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):定義函數和過程
 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()
2):函數的優勢
 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年, 真是惋惜了,只留下其哥哥孤守當年兄弟倆一塊兒打下來的江山。 此時你看着的老王離開的身影,感受你兒子跟他愈來愈像了。。。
3):函數的監控使用場景

 

   

六.函數式編程之參數詳解(1-2)

  1.函數的返回值詳解

  

 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 函數的返回值
View Code

總結:

    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).函數爲何要返回值?
    爲後面的程序調用,經過返回值的來進行判斷,從而完成相關代碼的邏輯。

 

  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
View Code

 

  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 #以上實例多練習體會其中的原理!不一一帖出來了。
View Code

 

  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 '''
View Code

    

    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 '''
View Code

   

    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 '''
View Code

    

    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 '''
View Code

    

    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 '''
View Code

 

 七.函數式編程與函數不一樣

  函數是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-2)

      

  

  在子程序中定義的變量稱爲局部變量,在程序的一開始定義的變量稱爲全局變量。

  全局變量做用域是整個程序,局部變量做用域是定義該變量的子程序。
 
   當全局變量與局部變量同名時:
  在定義局部變量的子程序內,局部變量起做用;在其它地方全局變量起做用。
   實例1:全局變量和局部變量的使用
 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
View Code

 

  實例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
View Code

  實例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 #列表,字典,集合,類等能夠修改。
View Code

 

 

九.遞歸  

  在函數內部,能夠調用其餘函數。若是一個函數在內部調用自身自己,這個函數就是遞歸函數。

  函數遞歸調用,在調用一個函數的過程當中又直接或間接地調用了本身稱之爲函數的遞歸調用

       本質就是一個重複的過程,必須有兩個明確的階段

      #一、回溯:一層一層地遞歸調用下去,沒進入下一層問題的規模都應該有所減小
      #二、遞推:遞歸必需要有一個明確的結束條件,在知足該條件的狀況下會終止遞歸,
     往回一層一層地結束調用

 遞歸特性:

  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
View Code

   

  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)
遞歸 vs while循環

 

 

十.高階函數和匿名函數

  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 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

現須要對這個員工信息文件,實現增刪改查操做

  1. 可進行模糊查詢,語法至少支持下面3種:
    1.   select name,age from staff_table where age > 22
    2.   select  * from staff_table where dept = "IT"
    3.       select  * from staff_table where enroll_date like "2013"
    4. 查到的信息,打印後,最後面還要顯示查到的條數 
  2. 可建立新員工紀錄,以phone作惟一鍵,staff_id需自增
  3. 可刪除指定員工信息紀錄,輸入員工id,便可刪除
  4. 可修改員工信息,語法以下:
    1.   UPDATE staff_table SET dept="Market" WHERE where dept = "IT"

注意:以上需求,要充分使用函數,請盡你的最大限度來減小重複代碼!

代碼地址:https://gitee.com/meijinmeng/Sqltest.git

相關文章
相關標籤/搜索