日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python自动华 (四)

發布時間:2024/9/5 python 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python自动华 (四) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Python自動化 【第四篇】:Python基礎-裝飾器 生成器 迭代器 Json & pickle

目錄:

  • 裝飾器
  • 生成器
  • 迭代器
  • Json & pickle 數據序列化
  • 軟件目錄結構規范
  • ?

    1. Python裝飾器

      裝飾器:本質是函數,(功能是裝飾其它函數)就是為其他函數添加附加功能

    ?

      原則:

        >不能修改被裝飾的函數的源代碼

        >不能修改被裝飾的函數的調用方式

    ?

      實現裝飾器知識儲備:

        >函數即“變量”?

        >高階函數

          a)把一個函數名當做實參傳給另外一個函數(在不修改源代碼的請情況下)

          b)返回值中包含函數名(不修改函數的調用方式)

        >嵌套函數

    ?      高階函數+嵌套函數=》裝飾器

    ??

    1.1 函數的調用順序:

      Python不允許函數在未聲明之前對其進行引用或者調用

        錯誤案例一:

    def foo():print 'in the foo'bar()foo() View Code

        錯誤案例二:

    def foo():print 'foo'bar()foo()def bar():print 'bar' View Code

      以上兩個案例都會報錯:NameError:?global?name?'bar'?is?not?defined

        正確案例一:

    def bar():print 'in the bar'def foo():print 'in the foo'bar()foo() View Code

        正確案例二:

    def foo():print 'in the foo'bar()def bar():print 'in the bar'foo() View Code

      (python為解釋執行,函數foo在調用前已經聲明了bar和foo,所以bar和foo無順序之分)

    1.2  高階函數

      高階函數需滿足以下兩個條件:

        a)某一函數當做參數傳入另一函數中(在不修改源代碼的請情況下)

        b)返回值中包含函數名(不修改函數的調用方式)

      高階函數示例:

    def bar():print("In the bar") def foo(func):res = func()return res foo(bar) View Code

      高階函數進階:

    def foo(func):return funcprint 'Function body is %s' %(foo(bar))print 'Function name is %s' %(foo(bar).func_name)foo(bar)()#foo(bar)() 等同于bar=foo(bar)然后bar()bar=foo(bar)bar() View Code

    1.3 內嵌函數和變量作用域

      定義:在一個函數體內創建另外一個函數,這種函數就叫內嵌函數(基于python支持靜態嵌套域)

      函數嵌套示范:

    def foo():def bar():print'in the bar'bar() foo() View Code

      局部作用域和全局作用域的訪問順序

    x=0 def grandpa():# x=1def dad():x=2def son():x=3print xson()dad() grandpa() View Code

        范例一:函數參數固定

    def decorartor(func):def wrapper(n):print'starting'func(n)print'stopping'return wrapper def test(n):print'in the test arg is %s' % n decorartor(test)('Tom') View Code

        范例二:函數參數不固定

    def decorartor(func):def wrapper(*args, **kwargs):print'starting'func(*args, **kwargs)print'stopping'return wrapper def test(n, x=1):print'in the test arg is %s' % n decorartor(test)('alex', x=2) View Code

      無參裝飾器

    import time def decorator(func):def wrapper(*args, **kwargs):start = time.time()func(*args, **kwargs)stop = time.time()print'run time is %s ' % (stop - start)printtimeoutreturn wrapper @decorator def test(list_test):for i in list_test:time.sleep(0.1)print'-' * 20, i # decorator(test)(range(10)) test(range(10)) View Code

      有參裝飾器

    import time def timer(timeout=0):def decorator(func):def wrapper(*args, **kwargs):start = time.time()func(*args, **kwargs)stop = time.time()print'run time is %s ' % (stop - start)printtimeoutreturn wrapperreturn decorator @timer(2) def test(list_test):for i in list_test:time.sleep(0.1)print'-' * 20, i # timer(timeout=10)(test)(range(10)) test(range(10)) View Code

    ?

    2. 生成器

      a = [i*2 for I in range(10)]?? #列表生成式

      一邊循環一邊計算的機制,稱為生成器:generator

      要創建一個generator,有很多種方法。

      第一種方法很簡單,只要把一個列表生成式的[]改成(),就創建了一個generator:

    >>> L = [x * x for x in range(10)] >>> L [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> g = (x * x for x in range(10)) >>> g <generator object <genexpr> at 0x1022ef630> View Code

    ?

      創建L和g的區別僅在于最外層的[]和(),L是一個list,而g是一個generator。

      如果要一個一個打印出來,可以通過next()函數獲得generator的下一個返回值:

    >>> next(g)0>>> next(g)1>>> next(g)4>>> next(g)9>>> next(g)16>>> next(g)25>>> next(g)36>>> next(g)49>>> next(g)64>>> next(g)81>>> next(g)Traceback (most recent call last):File "<stdin>", line 1, in <module>StopIteration View Code

    ?

      generator保存的是算法,每次調用next(g),就計算出g的下一個元素的值,直到計算到最后一個元素,沒有更多的元素時,拋出StopIteration的錯誤。

      當然,上面這種不斷調用next(g)實在是太變態了,正確的方法是使用for循環,因為generator也是可迭代對象

    >>> g = (x * x for x in range(10)) >>> for n in g: ... print(n) ... 0 1 4 9 16 25 36 49 64 81 View Code

    ?

      所以,我們創建了一個generator后,基本上永遠不會調用next(),而是通過for循環來迭代它,并且不需要關心StopIteration的錯誤。

      generator非常強大。如果推算的算法比較復雜,用類似列表生成式的for循環無法實現的時候,還可以用函數來實現?

      斐波拉契數列用列表生成式寫不出來,但是,用函數把它打印出來卻很容易:

    def fib(max):n, a, b = 0, 0, 1while n < max:print(b)a, b = b, a + bn = n + 1return 'done' View Code

      上面的函數可以輸出斐波那契數列的前N個數:

    >>> fib(10) 1 1 2 3 5 8 13 21 34 55 done View Code

      仔細觀察,可以看出,fib函數實際上是定義了斐波拉契數列的推算規則,可以從第一個元素開始,推算出后續任意的元素,這種邏輯其實非常類似generator。

      也就是說,上面的函數和generator僅一步之遙。要把fib函數變成generator,只需要把print(b)改為yield b就可以了:

    def fib(max):n,a,b = 0,0,1while n < max:#print(b)yield ba,b = b,a+bn += 1return 'done' View Code

    ?

      這就是定義generator的另一種方法。如果一個函數定義中包含yield關鍵字,那么這個函數就不再是一個普通函數,而是一個generator:

    >>> f = fib(6)>>> f<generator object fib at 0x104feaaa0> View Code

    ?

      這里,最難理解的就是generator和函數的執行流程不一樣。函數是順序執行,遇到return語句或者最后一行函數語句就返回。而變成generator的函數,在每次調用next()的時候執行,遇到yield語句返回,再次執行時從上次返回的yield語句處繼續執行。

    data = fib(10)print(data)print(data.__next__())print(data.__next__())print("干點別的事")print(data.__next__())print(data.__next__())print(data.__next__())print(data.__next__())print(data.__next__()) View Code

      #輸出

    <generator object fib at 0x101be02b0>11干點別的事235813 View Code

    ?

      在上面fib的例子,我們在循環過程中不斷調用yield,就會不斷中斷。當然要給循環設置一個條件來退出循環,不然就會產生一個無限數列出來。

      同樣的,把函數改成generator后,我們基本上從來不會用next()來獲取下一個返回值,而是直接使用for循環來迭代:

    >>> for n in fib(6):... print(n)...112358 View Code

    ?

      但用for循環調用generator時,發現拿不到generator的return語句的返回值。如果想要拿到返回值,必須捕獲StopIteration錯誤,返回值包含在StopIteration的value中:

    >>> g = fib(6)>>> while True:... try:... x = next(g)... print('g:', x)... except StopIteration as e:... print('Generator return value:', e.value)... break...g: 1g: 1g: 2g: 3g: 5g: 8Generator return value: done View Code

    ?

      還可通過yield實現在單線程的情況下實現并發運算的效果

    import time def consumer(name):print("%s 準備吃包子啦!" %name)while True:baozi = yieldprint("包子[%s]來了,被[%s]吃了!" %(baozi,name))def producer(name):c = consumer('A')c2 = consumer('B')c.__next__()c2.__next__()print("老子開始準備做包子啦!")for i in range(10):time.sleep(1)print("做了2個包子!")c.send(i)c2.send(i)producer("Tom") View Code

    ?

    3. 迭代器

      我們已經知道,可以直接作用于for循環的數據類型有以下幾種:

        一類是集合數據類型,如list、tuple、dict、set、str等;

        一類是generator,包括生成器和帶yield的generator function。

      這些可以直接作用于for循環的對象統稱為可迭代對象:Iterable。

      可以使用isinstance()判斷一個對象是否是Iterable對象:

    >>> from collections import Iterable >>> isinstance([], Iterable) True >>> isinstance({}, Iterable) True >>> isinstance('abc', Iterable) True >>> isinstance((x for x in range(10)), Iterable) True >>> isinstance(100, Iterable) False View Code

      而生成器不但可以作用于for循環,還可以被next()函數不斷調用并返回下一個值,直到最后拋出StopIteration錯誤表示無法繼續返回下一個值了。

      *可以被next()函數調用并不斷返回下一個值的對象稱為迭代器:Iterator

    ?

      可以使用isinstance()判斷一個對象是否是Iterator對象:

    1 >>> from collections import Iterator2 3 >>> isinstance((x for x in range(10)), Iterator)4 5 True6 7 >>> isinstance([], Iterator)8 9 False 10 11 >>> isinstance({}, Iterator) 12 13 False 14 15 >>> isinstance('abc', Iterator) 16 17 False View Code

      生成器都是Iterator對象,但list、dict、str雖然是Iterable,卻不是Iterator。

      把list、dict、str等Iterable變成Iterator可以使用iter()函數:

    >>> isinstance(iter([]), Iterator)True>>> isinstance(iter('abc'), Iterator)True View Code

    ?

      Python的Iterator對象表示的是一個數據流,Iterator對象可以被next()函數調用并不斷返回下一個數據,直到沒有數據時拋出StopIteration錯誤。可以把這個數據流看做是一個有序序列,但我們卻不能提前知道序列的長度,只能不斷通過next()函數實現按需計算下一個數據,所以Iterator的計算是惰性的,只有在需要返回下一個數據時它才會計算。

      小結:

        凡是可作用于for循環的對象都是Iterable類型;

        凡是可作用于next()函數的對象都是Iterator類型,它們表示一個惰性計算的序列;

        集合數據類型如list、dict、str等是Iterable但不是Iterator,不過可以通過iter()函數獲得一個Iterator對象。

        Python的for循環本質上就是通過不斷調用next()函數實現的,例如

    for x in [1, 2, 3, 4, 5]:pass View Code

        實際上完全等價于:

    # 首先獲得Iterator對象:it = iter([1, 2, 3, 4, 5])# 循環:while True:try:# 獲得下一個值:x = next(it)except StopIteration:# 遇到StopIteration就退出循環break View Code

    ?

    4. json和pickle

      用于序列化的兩個模塊

      json,用于字符串和python數據類型間進行轉換
      pickle,用于python特有的類型和python的數據類型間進行轉換
      

      Json模塊提供了四個功能:dumps、dump、loads、load
      pickle模塊提供了四個功能:dumps、dump、loads、load

      

    5. 軟件目錄結構規范

      設計軟件目錄結構為了達到以下兩點:

      >可讀性高: 不熟悉這個項目的代碼的人,一眼就能看懂目錄結構,知道程序啟動腳本是哪個,測試目錄在哪兒,配置文件在哪兒等等。從而非常快速的了解這個項目。

      >可維護性高: 定義好組織規則后,維護者就能很明確地知道,新增的哪個文件和代碼應該放在什么目錄之下。這個好處是,隨著時間的推移,代碼/配置的規模增加,項目結構不會混亂,仍然能夠組織良好。

      目錄組織方式:

      假設你的項目名為foo, 我比較建議的最方便快捷目錄結構這樣就足夠了:

    Foo/|-- bin/| |-- foo||-- foo/| |-- tests/| | |-- __init__.py| | |-- test_main.py| || |-- __init__.py| |-- main.py||-- docs/| |-- conf.py| |-- abc.rst||-- setup.py|-- requirements.txt|-- README View Code

    ?

      簡要解釋一下:

      >bin/: 存放項目的一些可執行文件,當然你可以起名script/之類的也行。

      >foo/: 存放項目的所有源代碼。(1) 源代碼中的所有模塊、包都應該放在此目錄。不要置于頂層目錄。(2) 其子目錄tests/存放單元測試代碼; (3) 程序的入口最好命名為main.py。

      >docs/: 存放一些文檔。

      >setup.py: 安裝、部署、打包的腳本。

      >requirements.txt: 存放軟件依賴的外部Python包列表。

      >README: 項目說明文件。

    轉載于:https://www.cnblogs.com/honey01/p/7201565.html

    總結

    以上是生活随笔為你收集整理的python自动华 (四)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。