目錄:python
1、裝飾器算法
2、迭代器與生成器json
3、內置方法詳解flask
4、Json與pickle數據序列化api
5、軟件目錄結構規範app
1、裝飾器ssh
定義:裝飾器自己是函數,(裝飾其餘函數),就是爲其餘函數添加附加功能。函數
原則:1.不能修改被裝飾函數的源代碼單元測試
2.不能修改被裝飾函數的調用方式測試
裝飾器應用詳解
實現裝飾器的知識儲備:
1.函數即「變量」
2.高階函數
3.嵌套函數
高階函數+嵌套函數-->裝飾器
__Author__ = 'Redleafage Zhang' import time def timmer(func): #裝飾器 def warpper(*args,**kwargs): start_time = time.time() func() stop_time = time.time() print('the func run time is %s' %(stop_time-start_time)) return warpper @timmer def test1(): time.sleep(3) #運行邏輯所花費的時間 print('in the test1') test1()
打印結果:
1.裝飾器之「函數即變量「
匿名函數:
calc = lambda x:x*3 #匿名函數,沒有名字的函數 print(calc(3)) #返回9
變量名至關於門牌號,存放的內容至關於房間裏的東西(佔內存空間),函數名也至關於門牌號,函數體(函數的具體內容)在房間裏面。以下圖:
2.高階函數:
a.把一個函數名看成實參傳給另一個函數(在不修改被裝飾函數源代碼的狀況下爲其添加功能)
b.返回值中包含函數名(不修改函數的調用方式)
def bar(): print("in the bar!") def test1(func): print(func) func() 能夠運行 test1(bar) #打印內存地址,bar只表明標示函數體的門牌號 func = bar func() #能夠運行,傳遞地址,至關於x=1,y=x
打印結果:
def bar(): time.sleep(3) print('in the bar') def test2(func): print(func) return func #print(test2(bar)) #兩次都打印地址 bar = test2(bar) #覆蓋以前的bar函數,至關於test2加上了新功能,函數調用方式沒有改變,python解釋器有專門的符號可解釋此過程,後面講 bar() # run bar
打印結果:
import time def bar(): time.sleep(3) print('in the bar') def test1(func): start_time = time.time() func() #run bar stop_time = time.time() print('the func run time is %s' % (stop_time-start_time) ) test1(bar)
打印結果:
3.嵌套函數
def foo(): #函數的嵌套,嵌套指在函數內部以def形式定義新函數 print('in the foo') def bar(): #局部變量 print('in the bar') bar() foo()
def test1(): #這叫函數的調用,不是嵌套。 test2() test1()
局部做用域與全局做用域的訪問順序
x=0 def grandpa(): #x=1 def dad(): x=2 def son(): x=3 print(x) son() dad() grandpa() #結果返回3
實例:
__Author__ = 'Redleafage Zhang' import time def timer(func): def deco(*args,**kwargs): #是否傳遞參數都無所謂了 start_time = time.time() func(*args,**kwargs) #run test1 stop_time = time.time() print('the func run time is %s' %(stop_time-start_time)) return deco # def timer(): # def deco(): # pass @timer #至關於test1 = timer(test1) def test1(): time.sleep(3) print('in the test1') @timer #test2 = timer(test2)= deco test2() = deco() def test2(name,age): print('test2',name,age) #print(timer(test1)) #打印內存地址 #test1 = timer(test1) #test1() #-->deco test1() test2('linda',22)
打印結果:
終極實例:
__Author__ = 'Redleafage Zhang' import time user,passwd = 'alex','abc123' def auth(auth_type): print("auth func:",auth_type) def outer_wrapper(func): def wrapper(*args, **kwargs): print("wrapper func args:", func) if auth_type == 'local': username = input("Username:").strip() password = input("Password:").strip() if user == username and passwd == password: print("\033[32;1mUser has passed authentication\033[0m") res = func(*args, **kwargs) print("---after authentication") return res else: exit("\033[31;1mInvalid username or password\033[0m") elif auth_type == '1dap': print("搞毛線1dap,不會。。。") return wrapper return outer_wrapper def index(): print('welcome to index page') @auth(auth_type = 'local') def home(): print('welcome to home page') return 'from home' # 沒執行結果,裝飾器改變告終果 @auth(auth_type = '1dap') def bbs(): print('welcome to bbs page') index() print(home()) #wrapper() bbs()
打印結果:
2、迭代器與生成器
列表生成式:
[i*2 for i in range(10)] #生成[0,2,4,6,8,10,12,14,16,18]
生成器:
經過列表生成式,咱們能夠直接建立一個列表。可是,收到內存限制,列表容量確定是有限的。並且,建立一個包含100萬個元素的列表,不只佔用很大的存儲空間,若是咱們僅僅須要訪問
前面幾個元素,那後面絕大多數元素佔用的空間都白白浪費了。
因此,若是列表元素能夠按照某種算法推算出來,那咱們是否能夠在循環的過程當中不斷推算出後續的元素呢?這樣就能夠沒必要建立完整的list,從而節省大量的空間,在python中,這種一邊
循環一邊計算的機制,稱爲生成器:generator。
要建立一個generator,有不少種方法。第一種方法很簡單,只要把一個列表生成式的[]改爲(),就建立了一個generator
1.生成器只有在調用時纔會生成相應的數據
2.調用生成器下一個數據:__next__()
3.生成器只記錄當前位置,只有一個next方法它不知道前面和後面,前面用完了就沒了,不能往回調用。每次只保留一個值。
generator很是強大, 若是推算的算法比較複雜,用相似列表生成式的for循環沒法實現的時候,還能夠用函數來實現。
好比,著名的斐波那契數列(Fibonacci),除第一個和第二個數外,任意一個數均可以由前兩個數相加獲得:
1,1,2,3,5,8,13,21,34,……
斐波那契數列用列表生成式寫不出來,可是,用函數把它打印出來卻很容易:
def fib(max): n,a,b = 0,0,1 while n < max: print(b) a,b = b,a+b n = n+1 return 'done'
注意,賦值語句:
a,b = b,a+b
至關於
t = (b,a+b) #t是一個tuple a = t[0] b = t[1]
而不是至關於
a=b a=1 b=2 a=b a=2 b=a+b b=2+2 = 4
仔細觀察,能夠看出,fib函數其實是定義了斐波那契數列的推算規則,能夠從第一個元素開始,推算出後續任意的元素,這種邏輯其實很是相似generator
也就是說,上面的函數和generator僅一步之遙。要把fib函數變成generator,只須要把print(b)改成yield b就能夠了:
def fib(max): n,a,b = 0,0,1 while n < max: #print(b) yield b a,b = a,a+b n += 1 return 'done'
調用生成器:
print(fib(10)) #返回地址 f = fib(10) print(f.__next__()) print(f.__next__()) print(f.__next__())
打印結果:
實例:
__Author__ = 'Redleafage Zhang' import time def consumer(name): print("%s 準備吃包子啦!" %name) while True: baozi = yield #None,由於是生成器,返回值後再也不執行,再次輸入__next__()纔會繼續執行 print("包子[%s]來了,被[%s]吃了!" %(baozi,name)) c = consumer("ChenRonghua") c.__next__() # b1= "韭菜餡" # c.send(b1) #把b1發送過去,被yield接收到 # c.__next__() def producer(name): c = consumer('A') #這一步只是把c變成生成器,不執行內容,next後纔會開始執行 c2 = consumer('B') c.__next__() c2.__next__() print("老子開始準備作包子啦!") for i in range(10): time.sleep(1) print("作了1個包子,分兩半!") c.send(i) c2.send(i) producer("alex")
打印結果:
迭代器
咱們已經知道,能夠直接做用於for循環的數據類型有如下幾種:
一類是集合數據類型,如list,tuple,dict,set,str等;
一類是generator,包括生成器和帶yield的generator function.
這些能夠直接做用於for循環的對象統稱爲可迭代對象:Iterable.
可使用isinstance()判斷一個對象是不是Iterable對象:
能夠被next()函數調用並不斷返回下一個值的對象稱爲迭代器:Iterator.
生成器確定是迭代器,迭代器不必定是生成器。
生成器都是Iterator對象,但list,dict,str雖然是Iterable,卻不是Iterator
把list,dict,str等Iterable變成Iterator可使用iter()函數:
你可能會問,爲何list,dict,str等數據類型不是Iterator?
這是由於Python的Iterator對象表示的是一個數據流,Iterator對象能夠被next()函數調用並不斷返回下一個數據,直到沒有數據時拋出StopIteration錯誤,能夠把這個數據流看做是
一個有序序列,但咱們卻不能提早知道數列的長度,只能不斷經過next()函數實現按需計算下一個數據,因此Iterator的計算是惰性的,只有在須要返回下一個數據時它纔會計算。
Iterator甚至能夠表示一個無限大的數據流,例如全體天然數。而使用 list 是永遠不可能存儲全體天然數的。(惰性計算:走到這一步再算,沒走到就不算)
凡是可用於for循環的對象都是Iterable類型:
凡是可做用於 next()函數的對象都是Iterator類型,它們表示一個惰性計算的序列:
集合數據類型如list,dict,str等是Iterable但不是Iterator,不過能夠經過iter()函數得到一個Iterator對象。
3、內置方法詳解
全部內置方法:
哈希:
若是直接搜索中文集,效率低,若是有500萬個數據,則須要循環500萬次,把無序的中文集經過映射轉換爲數字,並排序,查找的時候用折半查找的方式找對應的數字,提升效率。python
的字典是用哈希的方法實現的。MD5也屬於哈希
內置函數詳解:
__Author__ = 'Redleafage Zhang' print(all([0,-5,3])) #若是可迭代對象裏全部的元素都爲真(或者是空值),則返回真 print(any([0,-5.3]))#可迭代數據裏任意的數據爲真,則爲真,若是是空的,則返回假 a=ascii([1,2,'開外掛了']) #把內容轉換成字符串 print(type(a),[a]) print(bin(9)) #十進制轉二進制 print(bool(1)) #判斷真假 a=bytes("abcde",encoding="utf-8") b = bytearray("abcde",encoding="utf-8") print(b[0]) #打印ASCII碼 b[1] = 100 #不能賦值字符串,只能賦ASCII碼形式 # print(a) # print(a.capitalize(),a) 變大寫,不改變原字符串 print(callable([])) #判斷是否可調用,能加括號的可調用(好比函數),列表返回False print(chr(88)) #把數字對應ASCII碼字符打印出來 print(ord('a')) #把字符轉爲ASCII碼 code = "for i in range(10):print(i)" c = compile(code,'','exec')#exec表示能夠把字符串之造成代碼 exec(c) code = "1+3/2*6" #c = compile(code,'','eval') #eval計算數字 #eval(c) #CMD裏可運行 eval(code) #CMD裏可運行,把字符串變成字典 code = ''' def fib(max): n,a,b = 0,0,1 while n < max: #print(b) yield b a,b = b,a+b n = n+1 return 'done' #此時fib已是一個生成器,而不是一個函數,所以return是在異常測試時打印出來的東西,而不是函數的返回值 print(fib(10)) f = fib(10) print(f.__next__()) print(f.__next__()) print(f.__next__()) ''' py_obj = compile(code,"err.log",'exec') exec(py_obj) exec(code) #直接用exec也能夠,compile沒什麼用 a = {} print(dir(a)) #查參數有什麼方法能夠用 print(divmod(5,2)) #相除並返回商和餘數,歸爲元祖 def sayhi(n): #若是這個函數只使用一次,用def佔用空間 print(n) for i in range(n): #此種lambda沒法模擬 print(i) sayhi(3) #匿名函數,用完就釋放,不佔空間 print((lambda n:print(n))(5)) #(5)爲傳參 calc = lambda n:print(n) calc(5) #效果同上 calc = lambda n:3 if n<4 else n calc(5) res=filter(lambda n:n>5,range(10))#把大於5的過濾掉,返回迭代器 res = map(lambda n:n*2,range(10))#對傳入的每一個值按逗號前的方法得出結果 [i*2 for i in range(10)] for i in res: print(i) res = [lambda i:i*2 for i in range(10)]#效果同上 import functools res = functools.reduce(lambda x,y:x+y,range(10)) #從1加到9,x+y的值返回x ,y爲range(10)的下一個值 print(res) a = frozenset([1,4,333,212,33,33,12,4]) #不可變集合,不可增刪 print(globals()) #返回當前整個程序全部變量的keyvalue的格式,變量名是key,變量名對應的值是value print(hash('alex')) #把字符變成映射的數字 print(hex(122)) #把數字轉成16進制 def test(): local_var = 333 print(locals()) #打印當前函數全部的局部變量,以字典的形式 print(globals()) #打印結果無局部變量 test() print(globals().get('local_var')) #沒法取到函數裏的值,global只打印全局變量,不打印局部變量 print(oct(10)) #轉八進制 print(pow(3,5)) #3的5次方 round(1.3342,2) #保留兩位小數 slice(2,5,None) d = range(10) d[slice(2,5)] #至關於d[2:5],沒什麼用 a = {6:2,8:0,1:4,-5:6,99:11,4:22} print(sorted(a.items())) #把無序的字典按key排序 print(sorted(a.items(),key = lambda x:x[1])) #把無序的字典按value排序 print(a) #無序 a = [1,2,3,4] b = ['a','b','c','d'] for i in zip(a,b): #拼兩個列表,返回元組 print(i) __import__('decorator') #之後會用到
打印結果:
/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6 /Users/zhangshu/PycharmProjects/s14/day4/內置方法.py False True <class 'str'> ["[1, 2, '\\u5f00\\u5916\\u6302\\u4e86']"] 0b1001 True 97 False X 97 0 1 2 3 4 5 6 7 8 9 <generator object fib at 0x10410d200> 1 1 2 <generator object fib at 0x10410d2b0> 1 1 2 ['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values'] (2, 1) 3 0 1 2 5 None 5 0 2 4 6 8 10 12 14 16 18 45 {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x101eb85c0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/zhangshu/PycharmProjects/s14/day4/內置方法.py', '__cached__': None, '__Author__': 'Redleafage Zhang', 'a': frozenset({1, 33, 4, 12, 333, 212}), 'b': bytearray(b'adcde'), 'code': "\ndef fib(max):\n n,a,b = 0,0,1\n while n < max:\n #print(b)\n yield b\n a,b = b,a+b\n n = n+1\n return 'done' #此時fib已是一個生成器,而不是一個函數,所以return是在異常測試時打印出來的東西,而不是函數的返回值\n\nprint(fib(10))\nf = fib(10)\nprint(f.__next__())\nprint(f.__next__())\nprint(f.__next__())\n", 'c': <code object <module> at 0x1040f5a50, file "", line 1>, 'i': 18, 'py_obj': <code object <module> at 0x1040f5b70, file "err.log", line 2>, 'fib': <function fib at 0x104108598>, 'f': <generator object fib at 0x10410d2b0>, 'sayhi': <function sayhi at 0x101e62ea0>, 'calc': <function <lambda> at 0x104108ae8>, 'res': 45, 'functools': <module 'functools' from '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/functools.py'>} -652459854530933945 0x7a {'local_var': 333} {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x101eb85c0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/zhangshu/PycharmProjects/s14/day4/內置方法.py', '__cached__': None, '__Author__': 'Redleafage Zhang', 'a': frozenset({1, 33, 4, 12, 333, 212}), 'b': bytearray(b'adcde'), 'code': "\ndef fib(max):\n n,a,b = 0,0,1\n while n < max:\n #print(b)\n yield b\n a,b = b,a+b\n n = n+1\n return 'done' #此時fib已是一個生成器,而不是一個函數,所以return是在異常測試時打印出來的東西,而不是函數的返回值\n\nprint(fib(10))\nf = fib(10)\nprint(f.__next__())\nprint(f.__next__())\nprint(f.__next__())\n", 'c': <code object <module> at 0x1040f5a50, file "", line 1>, 'i': 18, 'py_obj': <code object <module> at 0x1040f5b70, file "err.log", line 2>, 'fib': <function fib at 0x104108598>, 'f': <generator object fib at 0x10410d2b0>, 'sayhi': <function sayhi at 0x101e62ea0>, 'calc': <function <lambda> at 0x104108ae8>, 'res': 45, 'functools': <module 'functools' from '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/functools.py'>, 'test': <function test at 0x104108bf8>} None 0o12 243 [(-5, 6), (1, 4), (4, 22), (6, 2), (8, 0), (99, 11)] [(8, 0), (6, 2), (1, 4), (-5, 6), (99, 11), (4, 22)] {6: 2, 8: 0, 1: 4, -5: 6, 99: 11, 4: 22} (1, 'a') (2, 'b') (3, 'c') (4, 'd') in the test1 the func run time is 3.002807140350342 Process finished with exit code 0
4、Jason與pickle數據序列化
Json:多語言可用,只能存放簡單數據
Pickle:只有python能用,能存放複雜數據(如函數)
import json info = { 'name':'alex', 'age':22 } f = open('test.text','w') print(json.dumps(info)) f.write(json.dumps(info)) #直接以字典格式存入文件 f = open('test.text','r') data = json.loads(f.read()) #恢復數據 print(data['age'])
打印結果:
pickle:
import pickle def sayhi(name): print("hello",name) info = { 'name':'alex', 'age':22, 'func':sayhi #pickel能夠存儲函數,而json不行 } f = open("test.text",''wb") print(pickle.dumps(info)) f.write(pickle.dumps(info)) #直接以字典格式存入文件 f = open("test.text","rb") data = pickle.loads(f.read()) #恢復數據 print(data)
打印結果:
注:pickle.dump(info,f) 等同於f.write(pickle,dumps(info))
data = pickle.load(f) 等同於pickle.loads(f.read())
寫程序時每dump一次,就要loadi 次,不要一次dump不少行,寧肯dump成好幾個文件。
5、軟件目錄結構規範
1.bin/: 存放項目的一些可執行文件,固然你能夠起名script/之類的也行。
2.foo/:存放項目的全部源代碼。(1)源代碼中的全部模塊、包都應該放在此目錄。不要只置於頂層目錄。(2)其子目錄test/存放單元測試代碼;(2)程序的入口最好命名爲main.py
3.docs/:存放一些文檔
4.setup.py:安裝、部署、打包的腳本
5.requirements.txt:存放軟件依賴的外部Python包列表
6.README:項目說明文件
除此以外,有一些方案給出了更多的內容。好比ICENSE.txt,ChangeLog.txt文件等,通常開源的時候會用到。
關於README的內容:
這個是每一個項目都應該有的一個文件,目的是要能簡要描述該項目的信息,讓讀者快速瞭解這個項目。
它須要說明如下幾個事項:
1.軟件定位,軟件的基本功能。
2.運行代碼的方法:安裝環境、啓動命令等。
3.簡要的使用說明。
4.代碼目錄結構說明,更詳細點能夠說明軟件的基本原理。
5.常見問題說明。
requirements.txt:
這個文件存在的目的是:
1.方便開發者維護軟件的包依賴。將開發過程當中新增的包添加進這個列表中,避免在setup.py安裝依賴時漏掉軟件包。
2.方便讀者明確項目使用了哪些Python包。
這個文件的格式是每一行包含一個包依賴的說明。一般是flask >= 0.10這種格式,要求是這個格式能被pip識別,這樣就能夠簡單的經過pip install -r requirements.txt來把全部的python包依賴
都安裝好了。
注意:從foo調main須要跨目錄
經過os方法找到主目錄,添加給環境變量,再導入其它模塊便可。