WEEK4:迭代器、裝飾器、軟件開發規範

  • 裝飾器
     1 import time
     2 def timer(func): #timer(test1) func=test1
     3     def deco(*args,**kwargs):
     4         start_time=time.time()
     5         res=func(*args,**kwargs) #run test1()
     6         stop_time=time.time()
     7         print("the func run time is %s" %(stop_time-start_time))
     8         return res
     9     return deco
    10 @timer #test1=timer(test1)
    11 def test1():
    12     time.sleep(3)
    13     print("in the test1")
    14 
    15 # 向函數內傳遞參數須要在裝飾器內部使用非固定參數*args和**kwargs
    16 @timer #test2=timer(test2)
    17 def test2(name):
    18     time.sleep(2)
    19     print("test2:",name)
    20 
    21 #獲取函數的返回值,須要將func的運行結果賦值給變量res
    22 @timer
    23 def test3():
    24     return "this is test3 name"
    25 
    26 #調用
    27 test1()
    28 test2("ssss")
    29 print(test3())
    View Code
    • 定義:本質是函數,(裝飾其餘函數)就是爲其餘函數添加附加功能
    • 原則:
      • 不能修改被裝飾的函數的源代碼
      • 不能修改被裝飾的函數的調用方式
         1 import time
         2 def timmer(func):
         3     def warpper(*args,**kwargs):
         4         start_time=time.time()
         5         func()
         6         stop_time=time.time()
         7         print("the func run time is %s" %(stop_time-start_time))
         8     return warpper
         9 @timmer
        10 def test1():
        11     time.sleep(3)
        12     print("in the test1")
        13 test1()
        View Code
    • 實現裝飾器知識儲備
      • 函數即「變量」
        • #補充知識:匿名函數
          calc=lambda x:x*3
          print(calc(3)) #結果爲9
        • 定義一個函數,就至關於將函數體賦值給一個變量,這個變量的名稱是函數名稱
      • 高階函數
        • 兩個條件,知足其中之一即是高階函數
          • 把一個函數名當作一個實參傳遞給另一個函數(在不修改被裝飾函數源代碼的狀況下爲其添加功能)
          • 返回值中包含函數名(不修改函數調用方式)
      • 嵌套函數
        在一個函數體內再用def定義函數
         1 x=0
         2 def grandpa():
         3     x=1
         4     def dad():
         5         x=2
         6         def son():
         7             x=3
         8             print(x)
         9         son()
        10     dad()
        11 grandpa()
        View Code
  • 生成器
      • 列表生成式 [ i*2 for i in range(10) ]或者 [ func(i) for i in range(10) ]  #佔用很大的內存空間
      • 列表生成器c=( func(i) for i in range(10) ) #訪問數據時纔會生成,不然不存在,因此不佔用內存,
    不支持切片
    #生成器只有在調用時纔會生成相應的數據
      • 生成器獲取下一個數據的方法c.__next__()
      • 生成器爲何沒法獲取上一個數據?生成器之因此省內存,緣由就是隻記住當前的數據(只記錄當前的位置),沒法獲取以前的數據,只能獲取下一個數據(只有一個__next__()方法)
    • 將斐波那契數列作成生成器
       1 def fib(max):
       2     n,a,b=0,0,1
       3     while n<max:
       4         yield b #轉換成生成式
       5         a,b=b,a+b
       6         n+=1
       7     return "--done--"
       8 g=fib(100)
       9 while True:
      10     try:
      11         n=g.__next__() #獲取下一個數值
      12         print(n)
      13     except StopIteration as e: #超出範圍處理
      14         print("Generator return value:",e.value)
      15         break
      View Code
    • 生成器的並行運算
       1 import time
       2 def consumer(name): #消費者
       3     print("%s 準備吃包子啦!"%name)
       4     while True:
       5         baozi=yield
       6         print("包子[%s]來了,被[%s]吃了!"%(baozi,name))
       7 def producer(name):
       8     c=consumer("A")
       9     c2=consumer("B")
      10     c.__next__()
      11     c2.__next__()
      12     print("老子開始準備作包子了")
      13     for i in range(10):
      14         time.sleep(1)
      15         print("作了兩個包子")
      16         c.send(i)
      17         c2.send(i)
      18 #協程
      19 producer("alex")
      20 
      21 # c=consumer("ChenRonghua")
      22 # c.__next__()
      23 # b1="韭菜餡"
      24 # c.send(b1) #send給yield傳值
      25 # #next只喚醒生成器可是不傳值,send喚醒後傳值
      View Code
  • 迭代器
    能夠直接做用於for循環的數據類型有如下幾種:一、集合數據類型,如list、tuple、dict、set、str等,二、generator,包括生成器和帶yield的generator function,這些直接做用於for循環的對象統稱爲可迭代對象:Iterable
    可使用isinstance()判斷一個對象是不是Iterable對象:
    from collections import Iterable
    isinstance((x for x in range(10)),Iterator) #True
    isinstance([],Iterator) #False,[]、{}、'abc'均爲False
    生成器都是迭代器對象,可是list、dict、str雖然都是可迭代的,卻不是迭代器,把list、dict、str等可迭代的數據類型變成迭代器,可使用iter()函數,例如iter([])或者iter('abc')

    • 小結
      凡是可做用於for循環的對象都是可迭代類型,
      凡是可做用於next()函數的對象都是迭代器類型,他們表示惰性計算的序列
      集合數據類型如list、dict、str等都是可迭代的,但不是迭代器,不過能夠經過iter()函數獲取一個迭代器對象
      python的for循環本質上就是不斷調用next()函數實現的
  • 內置函數
    • abs() #取絕對值
    • all() #可迭代對象中所有數據爲真則返回true,不然爲false,
    • any() #可迭代對象中有一個數據爲真則爲true,不然爲false,空也爲false
    • ascii() #將處理對象變成一個字符串(可打印的對象)
    • bin() #十進制數字轉成二進制
    • oct() #十進制數字轉成八進制
    • bool() #判斷數據的真假
    • bytearray() #可修改的二進制字節格式
    • callable() #判斷對象是否能夠調用
    • chr() #將數字變成ascii表中的字符
    • ord() #將ascii表中的字符變成數字
    • compile() #將字符串變成可以執行的代碼
      例如:code是一段函數直接變成的代碼
      py_obj=compile(code,"err.log","exec")
      exec(py_obj)
      或者直接用exec(code)執行,不須要compile
    • dir() #查看對象的方法函數
    • divmod() #相除以後返回餘數
    • eval() #將字符串變成字典
    • filter() #過濾出數據中本身想要的數據
    • map() #對傳入的每個值按照前面的函數處理
    • functools.reduce() #將這次處理結果遞交給下一次做爲輸入
    • frozenset() #凍結集合,將集合變爲沒法修改的集合
    • round() ##保留n位小數
    • sorted() #排序
    • zip() #將兩個列表按照元素位置拼接在一塊兒
  • json序列化和反序列化
    • 序列化
      import json
      info={
          "name":"alex",
          "age":22
      }
      f=open("test.txt","w")
      f.write(json.dumps(info))
      f.close()
    • 反序列化
      import json
      f=open("test.txt","r")
      data=json.loads(f.read())
      print(data["age"])
  • pickle序列化和反序列化
    • 序列化
      import pickle
      info={
          "name":"alex",
          "age":22
      }
      f=open("test.txt","wb")
      f.write(pickle.dumps(info)) #或者pickle.dump(info,f)
      f.close()
    • 反序列化
      import pickle
      f=open("test.txt","rb")
      data=pickle.loads(f.read()) #或者data=pickle.load(f)
      print(data["age"])
  • 軟件目錄結構規範
    • 目錄結構以下圖

      • 簡要解釋
        • bin/:存放項目的一些可執行文件,固然你能夠起名script/之類的也行
        • foo/:存放項目的全部源代碼
          • 源代碼中全部的模塊、包都應該放在此目錄。不要置於頂層目錄
          • 子目錄test/存放單元測試代碼
          • 程序的入口最好命名爲main.py
        • docs/:存放一些文檔
        • conf/:存放軟件運行所需的配置文件
        • setup.py:安裝、部署、打包的腳本
        • requirements.txt:存放軟件依賴的外部python包列表
          • 方便開發者維護軟件包依賴。開發過程當中新增的包添加進這個列表中,避免在setup.py安裝依賴時漏掉軟件包
          • 方便讀者明確項目使用了哪些python包
        • README:項目說明文件
          • 軟件定位,軟件的基本功能
          • 運行代碼的方法:安裝環境、啓動命令等
          • 簡要的使用說明
          • 代碼目錄結構說明,更詳細點能夠說明軟件的基本原理
          • 常見問題說明
    • 跨目錄調用
      • __file__:當前文件的相對路徑
      • 將當前工程目錄添加到環境變量
        import sys,os
        BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        sys.path.append(BASE_DIR)
      • 調用from conf import settingsfrom core import main   #from後面跟子文件夾名字,import後面跟子文件夾下面的.py文件的名字
相關文章
相關標籤/搜索