python之裝飾器、生成器、內置函數、JSON

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': '東野圭吾'}
相關文章
相關標籤/搜索