1、裝飾器:python
裝飾器,器在這裏的意思是函數,也就是裝飾函數。做用是給其餘函數添加新功能,它能夠不改變原有的函數,原來的函數和原來如出一轍,什麼都不須要改變,只須要在函數外部加上調用哪一個裝飾器就能夠了,裝飾器的做用就是不改變原來函數的調用方式,不改變原來函數的代碼,給它增長了一個新功能。可是不改變函數,給它增長新功能,那是不可能的,裝飾器只不過是偷偷改變了原來的函數而已,而原來的函數不知不覺。算法
學習裝飾器前的知識儲備:json
一、函數即變量,在python裏面函數就是一個變量,函數名就是變量名,函數名裏存着函數內存地址。它把函數體存在內存裏,在調用的時候從函數名裏面的內存地址來函數體運行這個函數。函數名後面加上小括號就是調用,只有函數名就是打印函數的內存地址。ssh
def test(): int(input('please enter you age:'))
test()
print(test)
運行結果:函數
please enter you age:20 <function test at 0x02A84270>
二、高階函數,若是函數的入參爲函數的話,那麼這個函數就是一個高階函數。學習
三、函數嵌套,函數嵌套就是在函數裏再定義一個函數,而不是調用一個函數。ui
def A(a): print("I am A") def B(b): print("a+b=", a+b) print("I am B") B(2) print("Over!!!") A(3)
瞭解以上知識後,咱們來寫一個簡單的裝飾器,用來統計函數運行時間。spa
import time
def fun():
time.sleep(3)
print('in the fun')
def test(func):
start_time = time.time()
func()
stop_time = time.time()
print('the func run time is %s' % (stop_time - start_time))
test(fun)
運行結果:code
1 in the fun 2 the func run time is 3.007230520248413
可是這樣的話,咱們每次都要將一個函數做爲參數傳遞給test1函數。改變了函數調用方式,以前執行業務邏輯時,執行運行bar(),可是如今不得不改爲test1(bar)。此時就要用到裝飾器。咱們就來想一想辦法不修改調用的代碼;若是不修改調用代碼,也就意味着調用bar()須要產生調用test1(bar)的效果。咱們能夠想到將test1賦值給bar,可是test1彷佛帶有一個參數……想辦法把參數統一吧!若是test1(bar)不是直接產生調用效果,而是返回一個與foo參數列表一致的函數的話……就很好辦了,將test1(bar)的返回值賦值給bar,而後,調用bar()的代碼徹底不用修改!orm
import time def Time(fun): def deco(): start_time = time.time() fun() stop_time = time.time() print('the func run time is :%s'%(stop_time - start_time)) return deco @Time def dos(): time.sleep(2) print('in the dos') dos()
運行結果:
in the dos the func run time is :2.0002448558807373
這樣,咱們就提升了程序的可重複利用性,當其餘函數須要調用裝飾器時,能夠直接調用。裝飾器在Python使用如此方便都要歸因於Python的函數能像普通的對象同樣能做爲參數傳遞給其餘函數,能夠被賦值給其餘變量,能夠做爲返回值,能夠被定義在另一個函數內。
1 import time 2 3 def Timing(fun): 4 5 def deco(*arg, **kwarg): 6 7 start_time = time.time() 8 9 fun(*arg, **kwarg) 10 11 stop_time = time.time() 12 13 print('the func run time is :%s'%(stop_time - start_time)) 14 15 return deco 16 17 @Timing 18 def tar(name, age): 19 20 time.sleep(2) 21 22 print('in the tar :', name, age) 23 24 tar('hk', 18)
運行結果:
1 in the tar : hk 18 2 the func run time is :2.000657081604004
下面是用裝飾器寫的一個實例,邏輯是運行程序,打印菜單,若是選擇後臺管理和添加商品就判斷是否登陸,若是用戶爲登陸就讓用戶登陸;查看商品就不須要判斷是否登陸。
1 import os 2 def login(): 3 ''' 4 若是成功登陸,就寫入到user文件中 5 :return: 6 ''' 7 print('login') 8 username = input('請輸入帳號:') 9 password = input('請輸入密碼:') 10 if username == 'admin' and password == '123456': 11 print('登陸成功!') 12 with open('user', 'a+') as fw: 13 fw.write(username) 14 else: 15 print('帳號密碼錯誤') 16 17 def auth(func): 18 def check(*args, **kwargs): 19 if os.path.exists('user'): 20 func(*args, **kwargs) 21 else: 22 print('未登陸') 23 login() 24 return check 25 @auth 26 def admin(): 27 print('welcome!') 28 29 def show(): 30 print('show!') 31 32 @auth 33 def add(): 34 print('add product') 35 36 def menu(): 37 msg = ''' 38 1 : 後臺管理 39 2 : 查看商品 40 3 : 添加商品 41 ''' 42 print(msg) 43 m = { 44 "1": admin, 45 "2": show, 46 "3": add 47 } 48 choice = input('請輸入你的選擇:').strip() 49 if choice in m: 50 m[choice]() 51 else: 52 print('輸入錯誤!') 53 menu() 54 if __name__ == '__main__': 55 menu()
2、生成器
生成器是個什麼東東?大概能夠理解爲一個迭代的對象,和list相似,不過生成器是用到這個裏面的數據時它纔會生成。生成器是按照某種規則生成的一個列表。因此不能像list那樣,直接索引取值,必須知道前一個值,才能知道後面一個值。
一、列表生成式
list = [x*x for x in range(1,11)] print(list)
[1, 4, 6, 9, 25, 36, 49, 64, 81, 100]
二、生成器(generator):要建立一個generator,只要把一個列表生成式的[]改爲(),就建立了一個generator。
g=(x*x for x in range(1,11)) print(g) <generator object fib at 0x033FFE10>
建立list和generator的區別就是外層的[]和(),打印generator須要使用next方法。
g = (x*x for x in range(1,11)) print(next(g)) print(next(g)) print(next(g)) print(next(g))
運行結果:
1 4 9 16
generator保存的是算法,每次調用next(g),就計算出g的下一個元素的值,直到計算到最後一個元素,沒有更多的元素時,拋出StopIteration的錯誤。可使用for循環來迭代。並且不會擔憂Stopiteration錯誤。
g = (x*x for x in rang(1, 11)) for i in g: print(i)
運行結果:
1 4 9 16 25 36 49 64 81 100
對於比較複雜的算法,用相似列表生成式的for循環沒法完成,這個時候可使用函數來實現。
def fib(num): n, a, b = 0, 0, 1 while n < num: print(b) a, b = b, a+b n = n+1 return 'done' f = fib(8)
運行結果:
1 1 2 3 5 8 13 21
上面函數和generator僅有的區別就是把print(b)變成yield b。
def fib(num): n, a, b = 0, 0, 1 while n < num: yield b a, b = b, a+b n = n+1 return 'done' f = fib(8) for i in f: print(i)
3、內置函數
print(any([1, 'n', 3, 4, 0])) # 判斷可迭代的對象裏面是否有一個爲真 print(all([1, 2, 3])) # 判斷可迭代對象裏面的值知否都爲真 print(bin(108)) # 十進制轉爲二進制 print(bool(0)) # 把一個對象轉爲布爾類型 print(bool(1)) # 把一個對象轉爲布爾類型 print(bytearray('ade', encoding='utf-8')) # 把字符串變成一個可修改的bytes print(callable('s')) # 判斷傳入的對象是否可調用 print(chr(2)) # 數字對應的ASCII碼 print(ord('A')) # 字符串對應的ASCII碼 print(dict(a=1, b=2)) # 轉爲字典 print(dir(2)) # 打印傳入對象的調用方法 print(eval('[]')) print(exec('def a():pass')) print(filter(lambda x: x > 5, [12, 3, 12, 2, 1, 2, 25])) # list裏面迭代對象篩選方法爲 x > 5 print(map(lambda x: x > 5, [1, 2, 3, 4, 5, 6])) print(frozenset({1, 2, 3, 4})) # 定義一個不可修改的集合 print(globals()) # 返回程序內的全局變量 print(locals()) # 返回程序的局部變量 print(hash('abc')) # 把一個字符串哈希成數字 print(hex(123)) # 數字裝換成16進制 print(max(111, 222)) # 取最大值 print(oct(12)) # 轉換成8進制 print(round(12.345, 2)) # 取2位小數 print(sorted([1, 3, 4, 5, 2, 2, 10, 0, 23, 15])) # 排序 dic = {1: 2, 3: 5, 4: 4, 8: 3, 6: 2} print(sorted(dic.items())) # 按字典key排序 print(sorted(dic.items(), key=lambda x: x[1])) # 按字典value排序 __import__('os')
運行結果:
True True 0b1101100 False True bytearray(b'ade') False 65 {'a': 1, 'b': 2} ['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes'] [] None <filter object at 0x008028B0> <map object at 0x00802910> frozenset({1, 2, 3, 4}) {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x006FA470>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:/Users/wgx/PycharmProjects/titled/group.py', '__cached__': None, 'a': <function a at 0x008042B8>} {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x006FA470>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:/Users/wgx/PycharmProjects/titled/group.py', '__cached__': None, 'a': <function a at 0x008042B8>} 9703036 0x7b 222 0o14 12.35 [0, 1, 2, 2, 3, 4, 5, 10, 15, 23] [(1, 2), (3, 5), (4, 4), (6, 2), (8, 3)] [(1, 2), (6, 2), (8, 3), (4, 4), (3, 5)]
4、匿名函數
匿名函數只能夠執行一次,匿名函數只能處理簡單的邏輯,不能寫循環判斷。匿名函數定義使用lambda關鍵字
d = lambda x,y:x+y print(s(1,3)
5、Json處理
import json dic = {'name': '白夜行', 'author': '東野圭吾'} print(json.dumps(dic)) # 將字典轉換成json串 fw = open('a.json', 'w') json.dump(dic, fw) # 將字典轉換成json串病寫到一個文件裏 s_json = '{"name": "hk", "age": 20, "status": true}' print(json.loads(s_json)) # 將json串轉換成字典 fr = open('b.json', 'r') print(json.load(fr)) # 從文件中讀取json串並轉換成字典
運行結果:
{"name": "\u767d\u591c\u884c", "author": "\u4e1c\u91ce\u572d\u543e"} {'name': 'hk', 'age': 20, 'status': True} {'name': '白夜行', 'author': '東野圭吾'}