python基礎之數據類型-面向對象

人生苦短,Python當歌! 此篇博客是本人學習python過程當中,總結的基礎知識點,但願能夠幫到有須要的朋友,若有不足或錯誤之處,但願評論指出,感謝你們!!


第一章 計算機基礎


1.1 硬件

​ 計算機的硬件由:CPU /內存 /主板 /硬盤 /顯卡等組成java

​ 內存:python

​ 優勢:存取速度快mysql

​ 缺點:斷電後數據所有丟失linux

​ 硬盤:c++

​ 優勢:斷電後數據也會永久保存git

​ 缺點:存取速度遠遠慢於內存程序員

1.2 操做系統:

操做系統用於協同或控制硬件之間進行工做面試

  • windows : win7 / win10/ xp ...
  • linux(開源,免費):
    • centos(公司主要用的)
    • ubuntu:適合我的開發,圖形化界面好
    • redhat:企業級
  • Mac 適合辦公

1.3 解釋器和編譯器

編程語言的開發者寫的一個工具,將用戶寫的代碼轉換成二進制交給操做系統去執行redis

1,4 解釋型語言和編譯型語言

  • 解釋型:寫完代碼後,交給計算機一行一行執行,邊解釋邊執行 如:python / PHP/Ruby...
  • 編譯型:寫完代碼後,編譯器將其變成另外一個文件,再交給計算機去執行 如 :c / c++ / java...

1.5 進制

對於計算機而言,不管文件儲存 / 網絡傳輸等本質上都是二進制.微信/QQ等發的信息,圖片,視頻都是二進制算法

進制:

  • 2進制: 計算機內部

  • 8進制

  • 10進制:人使用計算機通常都是10進制,計算機內部會將其轉換成二進制

  • 16進制:通常用於表示(用更短的內容表示更多的東西.通常是: \x 開頭

第二章 python 入門


2.1 編程是什麼

  1. 什麼是編程語言
    • 語言是一個事物與另外一個事物溝通的介質
    • 編程語言就是程序員與計算機溝通的介質
  2. 什麼是編程
    • 編程就是程序按照某種編程語言的語法規範將本身想要讓計算機作的事表達出來
    • 表達的結果就是程序,程序就是一系列的文件
  3. 爲何要編程
    • 在編程的過程當中,計算機就像是人的奴隸
    • 咱們編程的目的就是讓計算機代替人類去工做,從而解放人力

2.2 環境的安裝

  • 安裝解釋器:py2 / py3 (注意環境變量問題)
  • 安裝開發工具:pycharm

2.3 編碼

  • ASCII :8位表示一個東西,只能識別英文

  • Unicode(萬國碼): 一箇中文或字母等於四個字節,最多32位表示,內存進行數據計算時使用

  • utf-8:給萬國碼壓縮,一箇中文等於3個字節,一個英文一個字節,通常網絡傳輸和文件存儲時使用此編碼

  • gbk : 一箇中文兩個字節

  • gb2312

    注意:文件以什麼方式保存就要以什麼方式打開

2.4 解釋器編碼相關

  • py2默認解釋器編碼:ASCII

  • py3默認解釋器編碼:utf-8

    如想修改默認編碼,則可使用:

    # -*- coding:utf-8 -*-

2.5 變量

爲何要有變量?

爲某個值建立一個「外號」,之後在使用時候經過此外號就能夠直接調用。

  1. 變量的要求:
    • 只能包含數字 / 字母 / 下劃線
    • 不能是數字開頭
    • 不能包含python中的關鍵字
  2. 建議
    • 見名知意
    • 用下劃線鏈接

2.6 輸出 輸入

  1. 輸出:

    py2: print '你好'
    py3: print('你好')
  2. 輸入 : 獲得的內容永遠是字符串

    py2 raw_input("xxx")
    py3 input('xxx')
    #示例
    user_name = input("請輸入你的姓名:")
    password = input("請輸入你的密碼:")
    content = "你的用戶名是:" + user_name + "; 你的密碼是:" + password
    print(content)

2.7 註釋

# 單行註釋

'''
多行註釋
'''

2.8 if 條件語句

# :示例:讓用戶輸入一個數字,猜:若是數字 > 50,則輸出:大了; 若是數字 <= 50 ,則輸出:小了。 
num = input('請輸入一個數字') 
number = int(num) 
if number > 50:
    print('大了') 
else:
    print('小了')

2.9 循環

  1. while 循環

    while 條件表達式:
        循環體
    
     # 當條件表達式的返回值爲真時,則執行循環體中的語句,執行完畢後,從新判斷條件表達式的返回值,直到表達式的返回的結果爲假時,退出循環.
  2. for 循環

    for 某個變量 in 要循環的對象:
            循環體
    
     #  其中某個變量是用於保存讀取出的值,對象爲要遍歷或迭代的對象,能夠是任何有序的序列對象,如字符串.列表.元組等.循環體爲一組被重複執行的語句

    死循環考慮while, 有限循環優先考慮for循環

  3. break 語句

    意思爲結束當前循環

  4. continue 語句

    意思:當循環遇到continue時,再也不繼續往下走,而是回到當前循環

2.30 字符串格式化

  1. %s: (字符串佔位符)

    name = input('姓名:')
    do = input('在幹什麼:') 
    template = "%s在教室,%s。" %(name,do,) 
    print(template)
  2. %d (數字佔位符)

    template = "我是%s,年齡%d, 職業%s。" %("alex",73,'講雞湯',)
    print(template)
  3. %%

    name = 'alex' 
    template = "%s如今手機的電量是100%%" %(name,) print(template)

2.31 運算符

  1. 算數運算

    示例:
     1 ~ 100 之間全部的數相加。
    total = 0
    count = 1
    while count <=100:
        total += count 
        count  +=  1 
    print(total)
  2. 賦值運算

  3. 邏輯運算

    • or

      對於 or,若是有遇到 value= 1 or 9
          第一個值若是是轉換成布爾值若是是真,則value=第一值。
          第一個值若是是轉換成布爾值若是是假,則value=第二值。
          若是有多個or條件,則從左到右依次進行上述流程
    • and

      對於and,若是遇到 value= 1 and 9     
          若是第一個值轉換成布爾值是True,則value=第二個值
          若是第一個值轉換成布爾值是False,則value=第一個值。 
          若是有多個and條件,則從左到右依次進行上述流程
    • 優先級

      在沒有()的狀況下not 優先級高於 and,and優先級高於or,即爲( )>數學運算>not>and>or,同一優先級從左往右計算

      示例:
      not 2 > 1 and 3 < 4 or 4 > 5 and 2 > 1 and 9 > 8 or 7 < 6     False
      3 > 1 and 2 or 2 < 3 and 3 and 4 or 3 > 2       2

第三章 數據類型


3.1 None

表示空(無任何功能,專門用於提供空值)

3.2 整形(int)

  1. py2:整型除法只能保留整數位。

    from __future__ import division
    
    v = 9 /2
    print(v)  #保留所有值
  2. py3

    • 只有int
    • 整型除法保留全部。

3.3 布爾類型(bool)

只有兩個結果:True/False:
 0/''/[]/()/{}/set() 轉布爾時爲False,其他結果都爲Ture

3.4 字符串(str) :

  • 不可變類型,不可刪除或修改
  1. upper:轉大寫 lower:轉小寫

    name = 'alex'
    new_name = name.upper()
    print(new_name)   # ALEX
  2. isdigit:判斷是不是數字,但經常使用 isdecimal 來判斷

    v = '1'
    # v = '二'
    # v = '②'
    v1 = v.isdigit()  # '1'-> True; '二'-> False; '②' --> True
    v2 = v.isdecimal() # '1'-> True; '二'-> False; '②' --> False
    v3 = v.isnumeric() # '1'-> True; '二'-> True; '②' --> True
    print(v1,v2,v3)
    # 之後推薦用 isdecimal 判斷是不是 10進制的數。
  3. strip: 去除空白,也能夠去除換行符(\n)和指定字符串

    v1 = "alex "
    print(v1.strip())
    
    v1 = "alexa"
    print(v1.strip('al'))
  4. replace:替換

    content = '去你大爺的'
    con = content.replace('大爺','**')  #當替換的內容有多個時,後面能夠加入數字,表明替換前幾個內容
    print(con)   # 去你**的
  5. split:切割 ,獲得的是一個列表

    content = '12|22,33|44'
    con = content.split('|')
    print(con)  #['12', '22,33', '44']
  6. format:字符串格式化

    name = '我是{0},今年{1}'.format('Alex',20,)
    print(name)
  7. startswith:判斷以什麼開頭 endswith:判斷以什麼結尾 結果爲Ture/False

    name = 'alex'
    flag = name.startswith('al')
    print(flag)   # Ture
  8. encode:轉換編碼

    name = '張三' # 解釋器讀取到內存後,按照unicode編碼存儲:8個字節。
    v1 = name.encode('utf-8')
    print(v1)  # 轉換成了6個字節
  9. join: 循環某個元素,並以某個東西鏈接起來

    name = 'Alex'
    new_name = '-'.join(name)  #注意:join鏈接的必須的字符串,若是不是須要先轉化爲字符串再進行鏈接
    print(new-name)  # A-l-e-x
  10. isalnum() 判斷字符串是否由字母或數字組成

  11. isalpha() 判斷字符串只有字母組成

3.5 列表(list) :

  • 可變類型,須要新的變量去接收
  1. append:在列表末追加元素

    v = [1,2,3,4,5]
    v.append(6)
    print(v)   #[1,2,3,4,5,6]
  2. insert:在列表指定索引值前面加入元素

    v= [1,2,3,4]
    v.insert(0,6)
    print(v)  #[6,1,2,3,4]
  3. extend: 逐個加入

    v = [1,2,3]
    name = 'Alex'
    v.extend(name)   #加入的能夠是字符串/元組/列表/集合
    print(v)   #[1,2,3,A,l,e,x]
  4. remove:刪除指定元素

    v = [123,23,45]
    v.remove(23)
    print(v)   #[123,45]
  5. pop: 根據索引位置進行刪除

    v = [123,23,45]
    a = v.pop(0)    #pop()默認刪除最後一個元素,會將刪除的那個元素返回回去
    print(v,a)    #  123 [23,45]
  6. del ;刪除

    v = [123,23,45]
    del v[0]
    print(v)   #[23,45]
  7. 修改

    v = [123,23,45]
    v[0] = 11
    print(v)  #[11,23,45]
  8. reverse :反轉

    v = [123,23,45]
    v.reverse()
    print(v)  #[45,23,123]
  9. sort: 排序

    v= [2,6,4,8,1]
    v.sort(reverse=True)  #從大到小排列
    v.sort(reverse=False)  #從小到大排列
    v.sort()   #默認是從小到大排列
    print(v)
  10. 枚舉和索引

    lis = [11,22,33,44]
    for index ,item in enumerate(lis,1)
        print(index,item)
    
    print(lis.index(33))  # 2

3.6 字典(dict) : 無序

  1. 格式

    data = {鍵:值,鍵:值,鍵:值,鍵:值,鍵:值,鍵:值,}    #鍵值對
    嵌套中:
     # 值能夠用任何東西表示
     # 鍵不能用列表/字典/集合(等可變類型)表示,其餘均可以
  2. keys 取全部的鍵

    data = {11:22,33:44,55:66}
    for k in data.keys():
     print(k)    #11,33,55
  3. values 取全部的值

    data = {11:22,33:44,55:66}
    for v in data.values():
        print(v)  # 22,44,66
  4. items 取全部的鍵值對

    data = {11:22,33:44,55:66}
    for k,v in data.items():
        print(k,v)
    
     注意:
        a,b,c = [1,2,3]
        print(a,b,c) #a=1,b=2,c=3
  5. get取值

    info = {'k1':'v1','k2':'v2'}
    v1 = info['k1']      # v1
    v2 = info.get('k1')      # v1  (經常使用此方法)
    v3 = info.get('k111',666)    # 666 (不在字典範圍內則打印後面的內容)
    v4 = info.get('k111')    # None
  6. 修改 (存在就修改/不存在就增長)

    data = {11:22,33:44,55:66}
    data[11] = 99
    print(data)  #  {11: 99, 33: 44, 55: 66}
    data[77] = 88
    print(data)  #  {11: 22, 33: 44, 55: 66, 77: 88}
  7. 刪除 (del)

    data = {11:22,33:44,55:66}
    del data[11]  # 刪除了一個鍵值對
    print(data)   # {33:44,55:66}
  8. pop 刪除

    info = {'k1':'v1','k2':'v2'}
    result = info.pop('k2')  #v2 
    print(info,result)   #{'k1':'v1'} v2
  9. update 批量添加

    info = {'k1':'v1','k2':'v2'}   #不存在就添加,存在就覆蓋
    info.update({'k3':'v3','k4':'v4','k2':666})
    print(info)  # {'k1': 'v1', 'k2': 666, 'k3': 'v3', 'k4': 'v4'}

3.7 集合(set) ;

  • 無序 / 無重複 空集合: set()
  1. 交集 (intersection)

    a = {1,2,3,4,5,}
    b = {2,4,6,7}
    c = a.intersection(b)
    print(c)   #  {2, 4}
  2. 並集(union)

    a = {1,2,3,4,5,}
    b = {2,4,6,7}
    c = a.union(b)
    print(c)   #  {1, 2, 3, 4, 5, 6, 7}
  3. 差集(difference)

    a = {1,2,3,4,5}
    b = {2,4,6,7}
    c = a.difference(b)   #{1,3,5}
    c = b.difference(a)   #{6,7}
  4. 單個添加 ;add

    a = {1,2,3,4,5}
    a.add(67)  #只能添加單個元素
    print(a)   #{1, 2, 3, 4, 5, 67}
  5. 批量添加: update

    v = {1,2,3,4,}
    v.update({5,6,7})    #後面的只能是集合/字典/元組/列表,不能是單獨的幾個元素
    print(v)  #{1,2,3,4,5,6,7}
  6. 刪除: discard

    v = {1,2,45}
    v.discard(45)  #刪除指定元素
    print(v)     #{1,2}
  7. 注意

    #嵌套時
    列表/字典/集合  不能做爲集合裏面的元素

3.8 公共功能

  • len(計算長度) 均可以

  • 索引 集合是無序的因此沒有,其他都有

  • 切片 字典和集合沒有,其他都有

  • 步長 字典和集合沒有,其他都有 " 經過步長能夠反轉字符串:[ : : -1 ]"

  • for 循環 均可以

  • 刪除 字符串 / 元組 是不可變類型,因此不能刪除,其他都有

  • 修改 字符串 / 元組 是不可變類型,因此不能刪除,其他都有

第四章 文件操做


4.1 讀 / 寫 操做

  1. 讀取: r (read):只能讀不能寫,文件不存在就報錯

    #打開文件:
        object = open('某個文件',mode = 'r',encoding = '編碼')
    
    #讀取文件全部內容到內存:
        content = object.read() 
        print(content)
    
    #讀取文件的全部內容到內存,並按照每一行進行分割到列表中。
     content = object.readlines()
        print(content)
    
    # 讀取文件的第一行:
     content= object.readline()
     此時光標在第一行的末端
    
    #若是之後讀取一個特別大的文件
     for line in object:  #一行一行進行讀取
            line = object.strip()  #去除換行最後一個換行
         print(line)
    
    #關閉內容:
        object.close()
    • read(): 所有讀到內存

    • read(1)

      • 1表示一個字符

        obj = open('某個txt文件',mode='r',encoding='utf-8')
        data = obj.read(1) # 1個字符
        obj.close()
        print(data)
      • 1表示一個字節(二進制中)

        obj = open('某個txt文件',mode='rb')    # b:二進制的意思
        data = obj.read(1) # 1個字節
        obj.close()
  2. 寫入:w (write): 只能寫不能讀(先清空文件),文件不存在就新建

    #打開文件:
        object = open('某個文件或要新建的文件',mode = 'w',encoding = '編碼')
    
    #寫內容:
        object.write('xxx')
    
    #關閉文件:
        object.close()
    • write(字符串)

      obj = open('某個txt文件或要新建的文件',mode='w',encoding='utf-8')
      obj.write('你好')
      obj.close()
    • write(二進制)

      obj = open('某個文件或要新建的文件',mode='wb')
      
      # obj.write('你好'.encode('utf-8'))
      v = '你好'.encode('utf-8')
      obj.write(v)
      
      obj.close()
  3. 追加; a (append): 只能追加不能讀,不存在則新建

    #打開文件:
        object = open ('某個txt文件或要新建的文件',mode = 'a',encoding = '編碼')
    
    #寫內容:
        object.append()
    
    #關閉文件
        object.close()

4.2可讀可寫:

  • r+
    • 讀:默認從0的光標開始讀,也能夠經過 seek 調整光標的爲位置。
    • 寫:從光標所在的位置開始寫,也能夠經過 seek 調整光標的位置。
  • w+
    • 讀:默認光標永遠在寫入的最後或0,也能夠經過 seek 調整光標的位置。
    • 寫:先清空。
  • a+
    • 讀:默認光標在最後,也能夠經過 seek 調整光標的位置。而後再去讀取。
    • 寫:永遠寫到最後。

4,3 其餘操做:seek / tell / flush

  1. seek(光標字節位置),不管模式是否帶b,都是按照字節進行處理。

    obj = open('某個txt文件',mode='r',encoding='utf-8')
    obj.seek(3) # 跳轉到指定字節位置,讀取後面內容
    data = obj.read()
    obj.close()
    print(data)
    
    obj = open('a.txt',mode='rb')
    obj.seek(3) # 跳轉到指定字節位置
    data = obj.read()
    obj.close()
    print(data)
  2. tell(), 獲取光標當前所在的字節位置

    obj = open('a.txt',mode='rb')
    obj.read()
    data = obj.tell()
    print(data)
    obj.close()
  3. flush,強制將內存中的數據寫入到硬盤

    v = open('a.txt',mode='a',encoding='utf-8')
    while True:
        val = input('請輸入:')
        v.write(val)
        v.flush()
    v.close()

4.4 關閉文件

  1. v = open('a.txt',mode='a',encoding='utf-8')
    
    v.close()
  2. with open('a.txt',mode='a',encoding='utf-8') as v:
        data = v.read()
     # 縮進中的代碼執行完畢後,自動關閉文件

4.5 文件內容的修改

  1. with open('a.txt',mode='r',encoding='utf-8') as f1:
        data = f1.read()
    new_data = data.replace('飛灑','666')
    
    with open('a.txt',mode='w',encoding='utf-8') as f1:
        data = f1.write(new_data)
  2. 大文件修改

    f1 = open('a.txt',mode='r',encoding='utf-8')
    f2 = open('b.txt',mode='w',encoding='utf-8')  #先打開兩個文件,再進行操做
    for line in f1:      # 一行一行進行修改
        new_line = line.replace('要被修改的內容','被修改後的內容')
        f2.write(new_line)
    f1.close()
    f2.close()
    
    #另外一種寫法:
    with open('a.txt',mode='r',encoding='utf-8') as f1, open('c.txt',mode='w',encoding='utf-8') as f2:
        for line in f1:
            new_line = line.replace('要被修改的內容','被修改後的內容')
            f2.write(new_line)

第五章 函數


5.0 三元計算(三目計算)

v = 前面 if 條件 else 後面

if 條件: 
    v = '前面'
else:
    v = '後面'

5.1 函數基本認識

  1. 目前:面向過程編程 [可讀性差/可重複性差]

  2. 函數式編程

    • 本質:將N行代碼拿到別處並給他起個名字,之後經過名字就能夠找到這段代碼並執行
    • 場景
      • 代碼重複執行
      • 代碼量特別多超過一屏,能夠選擇經過函數進行代碼的分割
  3. 函數的基本結構

    #函數的定義
    def 函數名(參數):
        #函數內容
    #函數的執行
    函數名(參數)
    示例:
    def get_list_first_data():
        v = [11,22,33,44]
        print(v[0])
    get_list_first_data()
    
    #注意:函數若是不被調用,則內部代碼永遠不會執行
  4. 參數

    定義一個函數:給了函數一個名稱,指定了函數裏包含的參數,和代碼塊結構。
    
    這個函數的基本結構完成之後,你能夠經過另外一個函數調用執行,也能夠直接從 Python 命令提示符執行。
    示例:打印某個列表的元素
       def get_list_first_data(aaa): # aaa叫形式參數(形參)
        v = [11,22,33,44]
        print(v[aaa]) 
    
    get_list_first_data(1) # 調用函數時傳遞叫:實際參數(實參)
  5. 返回值

    '''
    函數沒有返回值,默認返回 None
    函數執行過程當中遇到return,則終止,下面代碼永遠不會執行
    能夠返回任意類型
    '''

    1554798588820

    須要一個變量去接收

    1554964735088

    示例:
       # 讓用戶輸入一段字符串,計算字符串中有多少A字符的個數。有多少個就在文件a.txt中寫多少個「嘻嘻嘻」。
        def get_char_count(data):
            sum_counter = 0
            for i in data:
                if i == 'A':
                    sum_counter += 1        
            return sum_counter
     def write_file(line):
         if len(line) == 0:
             return False  # 函數執行過程當中,一旦遇到return,則中止函數的執行。
             with open('a.txt',mode='w',encoding='utf-8') as f:
                 f.write(line)
         return True 
        content = input('請輸入:')
        counter = get_char_count(content)
        write_data = "嘻嘻嘻" * counter 
        status = write_file(write_data)
        if status:
            print('寫入成功')
        else:
            print('寫入失敗')

5.2 參數相關

  1. 位置參數 : (調用函數並傳入函數)

    1554881428408

  2. 關鍵字傳參:

    def func(num1,num2)
     print(num1,num2)
    func(num1=1,num2=2)
位置傳參和關鍵字傳參能夠混合使用:
########  位置傳參必定要在關鍵字傳參前面  ###########
  1. 默認參數 (默認參數推薦用不可變類型,慎用可變類型)

    def func(a1,a2,a3=1,a4=2)
     print(a1,a2,a3,a4)
    
    func(11,22)  #a3和a4 已有默認參數,因此沒必要再定義參數
    func(11,22,a3=10,a4=100)  #再次定義參數,覆蓋前面的參數
    • 當默認參數數可變類型時

      #注意一
      def func(a,b=[]):
          b.append(a)
          return b
      v1 = func(1)
      v2 = func(2,[11,22])
      v3 = func(3)
      
      print(v1,v2,v3)
      #[1,3] [11,22,2]  [1,3]
      
      #注意二:
      def func(a,b=[]):
          b.append(a)
          print(b)
      
      func(1)   #[1]
      func(2,[11,22])  #[11,22,2]
      func(3)    #[1,3]
  2. 萬能參數(打散)

    • *args:能夠接收任意個數的位置參數,並將其轉換爲元組

      • 調用函數無*

        def func(*args):
            print(args)
        
        func(1,2,3)  #打印func後內容,裏面能夠是列表集合等
      • 調用函數有*

        def func(*args):
            print(args)
        func(*(1,2,3,4))  
        # 無論裏面的內容是列表/集合都打印成元組,當裏面內容爲字典時,打印內容爲字典的key(鍵)
    • **kwargs : 能夠接收任意個數的關鍵字參數,並將其轉換爲字典

      • 調用函數無**

        def func(**kwages): 
         print(kwages)
        func(k1=1,k2=2)  #{'k1': 1, 'k2': 2}
      • 調用函數有**

        def func(**kwages):
         print(kwages)
        func(**{'k1':1,'k2':2})  #後面內容只能是字典
  3. 僅限關鍵字參數

    def func(a,b,*args,c):
        print(a,b)
        print(c)
    func(1,2,3,4.c=222)
    打印:1,2
         222
  4. *的做用

    a,b,*c = (1,2,3,4,5,6,7)
    print(a,b,c)   # 1 2 [3,4,5,6,7]
    
    a,*b,c = [11,22,33,44,55,66,77]
    print(a,b,c)  # 11 [22, 33, 44, 55, 66] 77
    
    a,*b,c = range(10)
    print(a,b,c)   # 0 [1, 2, 3, 4, 5, 6, 7, 8] 9

5.3 做用域 &函數嵌套

  1. python中

    • py文件 : 全局做用域

    • 函數 : 局部做用域

      • 一個函數就是一個做用域
    • 做用域查找數據規則 : 優先在本身的做用域查找數據,本身沒有再去上一級查找,而後上上級,直到全局,全局沒有就報錯

      #示例1:
       x = 10
       def func():
           x = 8
           print(x)  # 8
           def x1():
               print(x)  # 9
           x = 9
           x1()
           x = 10
           print(x)  # 10
       func()
      
      #示例2:
       x = 10
       def func():
           x = 8
           print(x)  # 8
           def x1():
               print(x) # 8
           x1()
           x = 9
           x1()  # 9
           x = 10
           print(x) # 10
       func()
  2. 子做用域中只能找到父級中的值,默認沒法從新爲父級中的變量進行賦值. (globol / nonlocal 能夠強制作)

    • global : 找到並改變全局中的變量

      # 示例
      name = "老男孩"
      def func():
          name = 'alex'
          def inner():
              global name
              name = 999
          inner()
          print(name)  # 'alex'
      func()
      print(name)  # 999
      # 聲明全局中存在這個變量
      
      def func():
          global name
          nmae = 'alex'
      func()
      print(name)  # alex
    • nonlocal : 找到並改變上一級中的變量

      #示例:
      name = "老男孩"
      def func():
          name = 'alex'
          def inner():
              nonlocal name 
              name = 999
          inner()
          print(name)  # 999
      func()
      print(name)  # "老男孩"
      • 補充:

        • 全局變量之後必須所有是大寫

          USER_LIST = [11,22,3]
          def func():
              name = 'asdf'
              USER_LIST.append(12)
              USER_LIST.append(name)
          func()
          print(USER_LIST)

5.4 函數小高級

  1. 函數名當作變量來使用:

    def func():
        print(123)    
    v1 = func  #指向的是同一內存地址
    v1()
    #注意:不帶括號指向的是內存地址,帶括號是調用函數
    
    def func():
        return 123
    func_list1 = [func,func,func]
    func_list2 = [func(),func(),func()]
    print(func_list1)  # 打印的是內存地址
    print(func_list2)  #打印的是 : [123,123,123]  調用函數
    info = {
        'k1':func,  #內存地址
        'k2':func(),  # 調用函數
    }
    print(info)
  2. 函數能夠當作參數進行傳遞

    1554966563632

    結果爲: 666 none none

5.5 lambda 表達式 (也叫匿名函數)

​ 用於表示簡單的函數

1554967425725

注意:列表全部方法的返回值基本都爲none,字符串全部方法的返回值基本都返回新值

5.6 內置函數

  • 其餘:

    • len / open / id / range / type /

    • all 可迭代對象中所有是true 纔是true

      l1 = [1,'alex','',0]
      print(all(l1))  # false
    • any 可迭代對象中有一個爲true就是true

      l1 = [0,'',1,'alex']
      print(any(l1))  # true
    • repr 返回一個對像的string形式

      s1 = 'alex'
      print(s1)  #  alex
      print(repr(si))  # 'alex'
    • zip 拉鍊方式

      lis = [1,2,3,4,5]
      tu = ('a','b','c')
      s1 = 'alex'
      obj = zip(lis,tu,s1)
      print(obj)  # 獲得是一個迭代器
      print(list(obj))  # [(1, 'a', 'a'), (2, 'b', 'l'), (3, 'c', 'e')]
  • 輸入輸出 :

    • print / input

      print(1,2,3,4,sep = '-')   # 1-2-3-4
  • 強制轉換

    • dict / list / tuple / int / str / bool / set

    • dict 建立字典的幾種方式

      1. 直接建立

      2. 元組的解構

        dic1 = dict([(1,'one'),(2,'two'),(3,'three')])
        dic2 = dict(one=1,two=2)
        print(dic1)  # {1: 'one', 2: 'two', 3: 'three'}
        print(dic2)  # {'one': 1, 'two': 2}
    • reversed 返回的是一個翻轉的迭代器

      l = [i for i in range(10)]
      obj = reversed(l)
      print(obj)  # 獲得的的是一個迭代器
      print(l)  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
      print(list(obj)) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
  • 編碼相關

    • Chr , 將十進制數字轉換成Unicode編碼中的對應字符串

      v = char(99)
      print(v)  # c
    • ord , 根據字符在Unicode編碼中找到其對應的十進制

      con  = ord('中國')
      print(con)  #  20013
  • 數學相關

    • abs() 絕對值

    • float() 轉換爲浮點型(小數)

    • max() 找到最大值

    • sum() 求和

    • round() 返回浮點數x的四捨五入值

      print(round(12.238,2))  #12.24
      print(round(12.234,2))  # 12.23
    • pow() 求一個數的冪

      v = pow(2,3)
      print(v)  # 2**3 = 8
    • divmod() 兩數相除的商和餘數

      a,b = divmod(103,5)
      print(a,b)  # a=20  b=3
    # 經過分頁對數據進行展現
    """
    要求:
        每頁顯示10條數據
        讓用戶輸入要查看的頁面:頁碼
    """
    USER_LIST = []
    for i in range(1,836):
        temp = {'name':'啦啦啦-%s' %i,'email':'123%s@qq.com' %i }
        USER_LIST.append(temp)
    # 數據總條數
    total_count = len(USER_LIST)
    # 每頁顯示10條
    per_page_count= 10
    # 總頁碼數
    max_page_num,a = divmod(total_count,per_page_count)
    if a>0:
        max_page_num += 1
    while True:
        pager = int(input('要查看第幾頁:'))
        if pager < 1 or pager > max_page_num:
            print('頁碼不合法,必須是 1 ~ %s' %max_page_num )
        else:
            """
            # 第1頁:USER_LIST[0:10] -> 0123456789
            # 第2頁:USER_LIST[10:20]
            # 第3頁:USER_LIST[20:30]
            """
    
            start = (pager-1) * per_page_count
            end = pager * per_page_count
            data = USER_LIST[start:end]
            for item in data:
                print(item)
  • 進制轉換相關

    • bin() 將十進制轉換成二進制

    • oct() 將十進制轉換爲八進制

    • hex() 將十進制轉換爲十六進制

    • int() 將其餘進制轉換爲十進制

      # 二進制轉化成十進制
      v1 = '0b1101'
      result = int(v1,base=2)    
      print(result)
      
      # 八進制轉化成十進制
      v1 = '0o1101'
      result = int(v1,base=8)
      print(result)
      
      # 十六進制轉化成十進制
      v1 = '0x1101'
      result = int(v1,base=16)
      print(result)
      #請將 ip = "192.168.12.79" 中的每一個十進制數轉換成二進制: 
       # 0010100100001010010001010010001010010 -> 十進制的值
      
      ip = "192.168.12.79"
      ip_list = ip.split('.')
      lis = []
      for i in ip_list:
          data = bin(int(i))
          con = data.replace(data[:2],'0'*(8-len(data[2:])))
          lis.append(con)
      mes = ''.join(lis)
      result = int(mes,base = 2)
      print(result)
  • 括號內帶 key

    • sorted 排序

      l1 = [22, 33, 1, 2, 8, 7,6,5]
      l2 = sorted(l1)
      print(l2) # [1, 2, 5, 6, 7, 8, 22, 33]
      
      l2 = [('大壯', 76), ('雪飛', 70), ('納欽', 94), ('張珵', 98), ('b哥',96)]
      print(sorted(l2,key= lambda x:x[1]))  # 返回的是一個列表,默認從低到高
      # [('雪飛', 70), ('大壯', 76), ('納欽', 94), ('b哥', 96), ('張珵', 98)]
      
      print(sorted(l2,key= lambda x:x[1],reverse=True)) # 從高到低
      # [('張珵', 98), ('b哥', 96), ('納欽', 94), ('大壯', 76), ('雪飛', 70)]
    • min 取最小值 (max的用法同樣)

      # 示例1:  以絕對值的方式取最小值:
      l1 = [33, 2, 3, 54, 7, -1, -9]
      print(min(l1,key = abs)  # 1
      
      #  示例2:
      dic = {'a': 3, 'b': 2, 'c': 1}
      print(min(dic))  # min 會默認按照字典的鍵去比較 
      # 結果獲得 a (按照ASCII碼對照表的大小)   
      print(min(dic,key = lambda a: dic[a]))  # c
      print(min(dic.values(),key=lambda x:x)) # 1
    • 總結:凡是能夠加key的,它會自動的將可迭代的對象中的每一個元素按照順序傳入key對應的函數中,返回的是循環的那個元素

  • 經過list取值的內置函數

    • reversed
    • zip
    • filter
    • map

5.7 高級一點的內置函數 (面試題相關)

  • map : 循環每一個元素(第二個參數),而後讓每一個元素執行函數(第一個參數),將每一個函數執行的結果保存到新的列表中,並返回.(至關於列表推導式的循環模式)

    v1 = [11,22,33,44]
    result = map(lambda x:x+100,v1)  #將列表裏元素每一個都加上100
    print(list(result)) # 特殊
  • filter : 篩選(至關於列表推導式的篩選模式)

    v1 = [11,22,33,'asd',44,'xf']
    
    def func(x):
        if type(x) == int:
            return True
        return False
    result = filter(func,v1) 
    print(list(result))   # [11, 22, 33, 44]
    
    #也可簡寫成以下:
    result = filter(lambda x: True if type(x) == int else False ,v1)
    print(list(result))
    # 或
    result = filter(lambda x: type(x) == int ,v1)
    print(list(result))
    
    # 示例二:
    ret = ['1', '2', '60', '', '5', '4', '3','','']
    ret = filter(lambda n:n,ret)
    print(list(ret))  # 出除了列表裏的空字符串,並無改變裏面元素的位置
  • reduce : 將多個元素變成一個元素

    import functools   #導入一個模塊
    v1 = ['wo','hao','e']
    
    def func(x,y):
        return x+y
    result = functools.reduce(func,v1) 
    print(result)
    
    result = functools.reduce(lambda x,y:x+y,v1)
    print(result)

5.8 函數中高級

  1. 函數能夠做爲返回值

    1555057236736

    面試題相關:

    1555057544021

  2. 閉包

    • 什麼是閉包:

      • 閉包只能存在嵌套函數中
      • 內層函數對外層函數非全局變量的應\引用,就會造成閉包
      • 被引用的非全局變量也稱做自由變量,這個變量會與內層函數產生一個綁定關係
      • 自由變量不會在內存中消失
      • 做用:保證數據的安全

      1555057869828

  3. 遞歸 :

    • 最大深度是1000:爲了節省內存空間,不讓用戶無限使用內存空間
    #遞歸打印斐波那契數
    def func(a,b):
        # 1
        # 1
        # 2
        # 3 
        # 5 
        print(b) 
        func(b,a+b)
    
    func(0,1)

5.9 裝飾器

  • 徹底遵循開放封閉原則:
    • 對代碼的拓展現開放的
    • 對源碼的修改是封閉的
  1. 裝飾器編寫的格式

    • 在不改變原函數內部代碼和調用方式的基礎上,在函數執行以前和以後自動執行某個功能
    def 外層函數(參數)
     def 內層函數(*args,**kwargs) 
         #函數執行以前
         data= 參數(*args,**kwags)
            #函數執行以後
         return data
        return 內層函數
  2. 應用

    def func(arg):
        def inner():
            v = arg()
             return v
         return inner
    
    # 第一步:執行func函數並將下面的函數當作參數進行傳遞,  至關於:func(index)
    # 第二步: 將func返回的值從新賦值給下面的函數名   index = func(index)
    
     @func
      def index():
         print(123)
            return 666
      ret = index()
      print(ret)
      # 先打印 123 ,在打印 666
    #示例:計算函數執行時間
    import time
    def base(func):
        def inner():
            start_time = time.time()  --->#函數執行以前
            v= func()
            end_tme = time.time()  ---->#函數執行以後
            print(end_time-start_time)
            return v
        return inner
    
    @base
    def func1():
        time.sleep(2)  # 函數執行延緩2秒
        print(123)
    func1()
    
    @base
    def func2():
        time.sleep(1)
        print(456)
    func2()
  3. 關於返回值

    def x1(func):
        def inner(*args,**kwargs):
            data = func(*args,**kwargs)
            return data
        return inner 
                           #func函數帶括號,執行 f1 函數,先打印'123',先將666返回給data,data再返回給v1
    @x1
    def f1():
        print(123)
        return 666
    v1 = f1()  # 獲得的是inner函數的返回值
    print(v1)
  4. 關於先後

    def base(func):
        def inner(*args,**kwargs):
            print('函數調用以前')
            data = func(*args,**kwargs) #執行原函數並獲取返回值
            print('調用原函數以後')
            return data
        return inner
    @base
    def index():
        print(123)
    ret= index()
    print(ret)  # None
  5. 帶參數的裝飾器

    • 基本格式

      def base(counter):
          def wrapper(func):
              def inner(*args,**kwargs):
                  data = func(*args,**kwargs) # 執行原函數並獲取返回值
                  return data
              return inner 
         return wrapper 
      @base(9)   
      def index():
          pass
      
       #先執行base函數,而後將返回值wrapper返回,變成不帶參數的裝飾器
    • 面試相關

      #寫一個帶參數的函,實現:參數是多少,被裝飾的函數就要執行多少次,返回最後一次執行的結果
      
      def base(counter):
          def wrapper(func):
              def inner(*args,**kwargs):
                  for i in range(counter):
                      data = func(*args,**kwargs) # 執行原函數並獲取返回值
                  return data
              return inner
          return wrapper
      
      @base(5)
      def index():
          return 8
      v = index()
      print(v)

5.6.0 推導式

  1. 列表推導式(也叫列表生成式)

    • 用一行代碼構建一個比較複雜有規律的列表

    • 基本格式

      v1 = [i for i in 可迭代對象]
      v2 = [i for i in 可迭代對象 if 條件]#條件爲true才進行append
      #示例
      v1 = [99 if i>5 else 66  for i in range(10)]  
      
      v2 = [lambda : 100 for i in range(10)]
      result = v2[9]()  # 100
      
      v3 = [lambda :i for i in range(10)]
      result = v3[5]()  # 9
      
      v4 = [lambda x:x*i for i in range(10)] # 新浪微博面試題
      # 1.請問 v4 是什麼?
      函數地址 
      # 2.請問 v4[0](2) 的結果是什麼?
      18
      
      def num():
          return [lambda x:i*x for i in range(4)]
      # num() -> [函數,函數,函數,函數]
      print([ m(2) for m in num() ])   # [6,6,6,6]
  2. 集合推導式

    v1 = { i for i in 'alex' }
  3. 字典推導式

    v1 = { 'k'+str(i):i for i in range(10) }
  4. 生成器推導式:

    # def func():
    #     result = []
    #     for i in range(10):
    #         result.append(i)
    #     return result
    # v1 = func()
    v1 = [i for i in range(10)] # 列表推導式,當即循環建立全部元素。
    print(v1)
    
    # def func():
    #     for i in range(10):
    #         yield i
    # v2 = func()
    v2 = (i for i in range(10)) # 生成器推導式(非元組推導式),建立了一個生成器,內部循環爲執行。

    1557913747260

第六章 : 模塊(類庫)


穿插:

  • py2:
    • xrange:不會再內存中當即建立,而是在循環時,邊循環邊建立.
    • range:在內存中當即把全部的值創建
  • py3:
    • range : 不會再內存中當即創建,而是在循環時邊循環邊建立
    • py3中沒有xrange
  • 對於包的定義:
    • py2:必須得有__init__.py文件
    • py3:不須要,但建議每次都加上

6.0 模塊的基本認識

  • 爲何要有模塊
    • 拿來主義,提升開發效率
    • 便於管理維護
  • 什麼是腳本:腳本就是py文件,長期保存代碼的文件
  1. 內置模塊

    • 內置模塊是python自帶的功能,在使用內置模塊相應的功能時,須要先導入再使用
  2. 第三方模塊 :

    • 下載-->安裝-->使用
    1.找到python所在的根目錄-->再找到Scripts目錄-->最後找到pip.exe
    2.把pip.exe所在的目錄添加到環境變量中
    3.pip install 要安裝的模塊名稱   #pip install xlrd
    
    #安裝完成後,若是導入不成功
     - 重啓pycharm
         - 安裝錯了
  3. 自定義模塊

    • 本身寫一個模塊(一個py文件): aaa.py

      def f1():
          prinrt('f1')
      def f2():
          print('f2')
    • 在另外一個py文件中調用模塊中的功能 :a1.py

      #調自定義模塊中的功能
      import aaa
      aaa.f1()
      aaa.f2()
    • 運行

      a1.py
  4. 什麼是模塊

    • py文件 寫好了的,對程序員提供某方面功能的文件
  5. 什麼是包

    • 文件夾,儲存了多個py文件的文件夾
    • 若是導入的是一個包,這個包裏的模塊默認是不能用的
    • 導入一個包至關於執行了__init__ .py文件中的內容

6.1 模塊的調用

  1. 示例一:
示例:
# xxx.py

def show():
    print('nihao')
def func():
    pass

print(111)
#導入模塊,加載此模塊中的全部值到內存(一)
import xxx
print(222)
##調用模塊中的函數
xxx.func()
#導入模塊(二)
from xxx import func,show
from xxx import func
from xxx import *
func()
#導入模塊(三)
from xxx import func as f  #起別名
def func():
    print(222)
f()
  1. 示例二:

    xxxxxx  #(某個文件夾)
       -jd.py  #裏面有個f1函數
       -tb.py
       -pdd.py
    import xxxxxx.jd
    jd.f1()
    from xxxxxx import jd
    jd.f1()
    from xxxxxx.jd import f1
    f1()
  • 第一次導入模塊執行三件事:
    • 在內存中建立一個以模塊名命名的名稱空間
    • 執行此名稱空間全部的可執行代碼
    • 經過 模塊. 的方式引用模塊裏面的代碼
  • 總結:
    • 模快和要執行的py文件在同一目錄且須要模塊中的不少功能時,推薦使用:import 模塊
    • 其餘推薦:from 模塊 import 模塊 模塊.函數()
    • 其餘推薦:from 模塊.模塊 import 函數 函數()

6.1 包的導入

  1. 導入一個包(文件夾)至關於執行了這個包下的__init__文件,並不至關於把這個包下的全部文件都導入進來了

    1559820151235

6.2 內置模塊

1.random

  • random,randint
import random   

def get_random_code(length = 6):
    data = []
    for i in range(length):
        v = random.randint(65,90)
        data.append(chr(v))
    return  ''.join(data)
code = get_random_code()
print(code)
import random # 導入一個模塊
v = random.randint(起始,終止)  #獲得一個隨機數
  • random.unifrom

    import random
    
    a = random.unifrom(3,5)
    print(a)  # 返回的是3-5之間的一個浮點數
  • random.random

    print(random.random())  #獲得是一個0-1之間的浮點數

2.hashlib :

  • 做用: ,密文登入驗證 / 檢驗文件的一致性

  • 用於加密相關的操做,把一個大的數據切分紅不一樣塊,分別對不一樣的塊進行加密彙總的結果,和直接對總體數據加密的結果是一致的

  • 將bytes類型字節轉化成固定長度的16進制數字組成的字符串

  • 不一樣的bytes利用相同的算法轉化的結果必定不一樣

  • 相同的bytes利用相同的算法轉化的結果必定相同

  • haslhib 算法不可逆

  • 將指定的'字符串'進行加密

    import hashlib
    def get_md5(num):
        obj = hashlib.md5()  # 獲取一個加密對象
        obj.update(num.encode('utf-8')) # 使用加密對象的update進行加密    
        return obj.hexdigest()  # 經過hexdigest獲取加密效果
    val = get_md5('某段數字')
    print(val)
  • 加鹽 : (讓密碼更加安全)

    import hashlib
    
    def get_md5(data):         # md5括號內的內容越長,越不容易被破解
        obj = hashlib.md5("sidrsicxwersdfsaersdfsdfresdy54436jgfdsjdxff123ad".encode('utf-8'))
        obj.update(data.encode('utf-8'))
        result = obj.hexdigest()
        return result
    
    val = get_md5('123')
    print(val)
  • 應用

    import hashlib
    USER_LIST = []
    def get_md5(data):
        obj = hashlib.md5("12:;idrsicxwersdfsaersdfsdfresdy54436jgfdsjdxff123ad".encode('utf-8'))
        obj.update(data.encode('utf-8'))
        result = obj.hexdigest()
        return result
    def register():
        print('**************用戶註冊**************')
        while True:
            user = input('請輸入用戶名:')
            if user == 'N':
                return
            pwd = input('請輸入密碼:')
            temp = {'username':user,'password':get_md5(pwd)}
            USER_LIST.append(temp)
    def login():
        print('**************用戶登錄**************')
        user = input('請輸入用戶名:')
        pwd = input('請輸入密碼:')
    
        for item in USER_LIST:
            if item['username'] == user and item['password'] == get_md5(pwd):
                return True
    register()
    result = login()
    if result:
        print('登錄成功')
    else:
        print('登錄失敗')
  1. 密碼 不顯示,(只能在終端運行)

    import getpass
    
    pwd = getpass.getpass('請輸入密碼')
    if pwd == '123'
     print('輸入正確')

3. sys

  • python解釋器相關的數據
  1. sys.getrefcount : 獲取一個值的應用計數

    import sys  #導入模塊
    a = [1,2,3]
    b = a
    print(sys.getrefcount(a)) 
    #結果爲:3   至關於a被使用了三次
  2. sys.getrecursionlimit : python中默認支持的遞歸數量

    import sys 
    print(sys.getrecursionlimit())
    # 結果爲 :1000
    
    修改最大遞歸次數:
        import sys
     sys.setrecursionlimit(10000)
  3. sys.stdout.write 相似於print打印

    • \n 換行

    • \t 製表符

    • \r 回到當前行的起始位置

      print('1231你好你好你好23\r',end='')
      print('你好',end='')
      
      #因爲\r的存在,回到了當前行的起始位置,沒有換行,只會打印'你好'
  4. sys.argv : 命令行參數,第一個元素是程序自己路徑

    #示例:
    import sys
    
    if len(sys.argv) < 3:
        print('參數不夠,請從新運行')
    else:
        file_path = sys.argv[1]
        content = sys.argv[2]
        with open(file_path,mode='w',encoding='utf-8') as f:
            f.write(content)
  5. sys.path 會自動將當前目錄的路徑添加到sys.path列表中

    # 若是想要引用自定義的模塊,要麼將這個模塊放在當前目錄下面,要麼手動添加到sys.path中
    
    '''
    sys.path 列表中的第一個元素老是當前執行腳本的父目錄
    '''
  6. sys.modules 查看導入了那些模塊

4.os

  • 處理和操做系統相關的數據
  1. os.path.exists(path) , 若是path存在,返回True;若是path不存在,返回False

  2. os.path.getsize() 獲取文件的大小

    a = os.path.getsize(r'D:\python全棧\網絡編程\day28\one\server.py')
    print(a)   # 693
  3. os.path.abspath() : 獲取一個文件的絕對路徑

    path = '某個須要查看路徑的文件' 
    
    import os
    v1 = os.path.abspath(path)
    print(v1)
  4. os.path.dirname : 獲取路徑的上級目錄(不判斷路徑是否存在)

    import os
    v = r"C:\python36\新建文件夾\python36.exe D:/第三週/day14.py"
    print(os.path.dirname(v))
    
    #C:\python36\新建文件夾\python36.exe D:/第三週   一級一級往上走
  5. os.path.split 把路徑中的路徑名和文件名切分開,結果是元組

    import os
    res = os.path.split(r'd:/aaa/bbb/ccc/a.txt')
    print(res)  # ('d:/aaa/bbb/ccc', 'a.txt')
  6. os.path.join : 路徑的拼接

    import os
    path = "C:\python36\新建文件夾\python36.exe" 
    v = 'n.txt'
    
    result = os.path.join(path,v)
    print(result)
    #C:\python36\新建文件夾\python36.exe \n.txt
    
    result = os.path.join(path,'n1','n2','n3')
    print(result)
    #C:\python36\新建文件夾\python36.exe \n1\n2\n3
  7. os.listdir :查看一個目錄下全部的文件(第一層)

    import os
    result  = os.listdir(r'D:\untitled')
    for i in result:
        print(i)
  8. os.walk : 查看一個目錄下全部的文件(全部層)

    import os
    
    result = os.walk(r'D:\untitled')
    for a,b,c in result:
        # a,正在查看的目錄 b,此目錄下的文件夾  c,此目錄下的文件
        for item in c:
            path = os.path.join(a,item)
            print(path)
  9. os.path.basename() :獲取文件名稱

返回path最後的文件名,若是path以 / 結尾,就返回空值
  
  a = os.path.basename(r'D:\python全棧\網絡編程\day28\four')
  print(a)  # 結果爲: four
  
  a = os.path.basename('D:\python全棧\網絡編程\day28\four/')
  print(a)  # 結果:啥都沒有,空
  1. 轉義 : 'r'
v1 = r"D:\code\s21day14\n1.mp4"  (推薦)
  print(v1)
  # D:\code\s21day14\n1.mp4
  
  v2 = "D:\\code\\s21day14\\n1.mp4"  (不推薦)
  print(v2)
  # D:\code\s21day14\n1.mp4
  1. os.makedirs 建立目錄和子目錄

    1555485829184

  2. os.rename 重命名

import os
   os.rename('某個文件的名字','想要修改後的名字')
#練習:
   import os
   #1.讀取文件大小(字節)
   file_size = os.stat('某個文件').st_size
   #2. 一點一點讀取文件
   read_size = 0
   with open('某個文件',mode='rb') as f1,open('將要寫入的文件',mode='wb') as f2:
       while read_size < file_size:
           chunk = f1.read(1024) #每次最多去讀取1024字節
           f2.write(chunk)
           read_size += len(chunk)
           val = int(read_size / file_size * 100)   #查看打印進度
           print('%s%%\r' %val ,end='')
  1. 刪除

    # 刪除文件
    os.remove('文件名')
    
    # 刪除目錄(必須是空目錄)
    os.removedirs('目錄名')
  2. os.getcwd 查看工做目錄

    os.chdir 改變工做目錄

  3. os.urandom(16) 獲取一個隨機的16字節大小的字符串

  4. # 和執行操做系統命令相關
    
    os.popen/os.system
    import os
    os.system('dir')
    ret = os.popen('dir')
    print(ret.read())

5.json&pickle

  • 序列化:將內存中的數據轉換成字符串,用以保存文件或經過網絡傳輸

  • 反序列化:從文件或網絡中獲取的數據轉換成內存中原來的數據類型

  • json : 一個特殊的字符串 [長得像列表/字典/字符串/數字/真假]

    • 優勢:全部語言通用;缺點:只能序列化基本的數據類型
    • json.dumps 序列化
    • json.loads 反序列化
    • 一般都是一次性讀 一次性寫,用於存儲或者網絡傳輸
    import json
    #序列化:將python的值轉換爲json格式的字符串
    v = [11,22,{'k1':'v1'},True,'ggg']
    v1 = json.dumps(v)
    print(v1)    #"[11, 22, {"k1": "v1"}, true, "ggg"]"
    
    #反序列化 : 將json格式的字符串轉換成python的數據類型
    v2 = '["alex",123]'
    print(type(v2))  #字符串類型
    v3 = json.loads(v2)
    print(v3,type(v3))   #['alex', 123] <class 'list'>
  • 字典或列表中若有中文,序列化時想要保留中文顯示

    v = {'k1':'alex','k2':'李傑'}
    
    import json
    val = json.dumps(v,ensure_ascii=False)
    print(val)
  • 注意:

    • json 最外層必須是容器類的,如列表/字典,元組會被轉換爲列表.
    • 裏面的內容能夠是:str int bool list tuple 集合不能存在於json中
    • 字串必須使用雙引號(" ")鏈接
    # 將json類型的結果寫到文件中
    import json
    with open('a.txt',mode='w',encoding='utf-8') as f:
        json.dumps([1,2,3],f,ensure_ascii=False)
    
    # 從文件中讀取json類型結果   
    with open('a.txt',mode='r',encoding='utf-8') as f:
        con = json.loads(f)
        print(con)
    # 把須要序列化的對象.經過屢次序列化的方式, 用文件的write方法,把屢次序列化後的json字符串,寫到文件中.
    
    with open('b.txt',mode='at',encoding='utf-8') as f:
        f.write(json.dumps([1,2,3]) + '\n')
        f.write(json.dumps([4,5,5]) + '\n')
    
    #  把分次序列化的json字符串,反序列化回來
    with open('b.txt',mode='rt',encoding='utf-8') as f:
        for x in f:
            print(json.loads(x.strip()))
  • pickle:優勢:python中全部的東西都能被他序列化(轉換爲bytes類型) 缺點:序列化的內容只有python認識

    • dumps loads 只能用於網絡傳輸

      l1 = [1, 2, 3]
      
      import pickle
      st = pickle.dumps(l1)
      print(st)  # b'\x80\x03]q\x00(K\x01K\x02K\x03e.'
      
      l2 = pickle.loads(st)
      print(l2,type(l2))  # [1, 2, 3] <class 'list'>
    • dump load 直接寫入文件(還能夠寫入函數名,對象)

6.shutil

  • 刪除目錄

    import shutil
    shutil.rmtree('要刪除的目錄')
  • 重命名

    import shutil
    shutil.move('原目錄','修改後的目錄')
  • 壓縮文件 shutil.make_archive

    import shutil
    shutil.make_archive('要壓縮的文件','文件的後綴名(如zip)','要壓縮到的路徑')
    
    #示例:
    import shutil
    shutil.make_archive('xxx','zip','D:\第三週')
  • 解壓文件 shutil.unpack_archive

    import shutil
    shutil.unpack_archive('要解壓的文件',extract_dir=r'D:\code\xxxxxx\xxxx',format='zip')
    示例:
    import os
    import shutil
    from datetime import datetime
    ctime = datetime.now().strftime('%Y-%m-%d %H-%M-%S')
    
    # 1.壓縮lizhongwei文件夾 zip
    # 2.放到到 code 目錄(默認不存在)
    # 3.將文件解壓到D:\x1目錄中。
    
    if not os.path.exists('code'):   #判斷路徑是否存在
        os.makedirs('code')
    shutil.make_archive(os.path.join('code',ctime),'zip','D:\code\s21day16\lizhongwei') #壓縮文件
    
    file_path = os.path.join('code',ctime) + '.zip'  #兩個路徑拼接
    shutil.unpack_archive(file_path,r'D:\x1','zip')  #解壓文件
  • 拷貝文件

    shutil.copy2('原文件', '現文件')
  • 拷貝目錄

    shutil.copytree("原目錄", "新目錄", ignore=shutil.ignore_patterns("*.pyc"))  # ignore後面是不拷貝的內容
  • 獲取磁盤使用空間

    total, used, free = shutil.disk_usage(".")
    print("當前磁盤共: %iGB, 已使用: %iGB, 剩餘: %iGB"%(total / 1073741824, used / 1073741824, free / 1073741824))

7.time&datetime

  • UTG/GMT 世界時間
  • 本地時間 本地時區的時間
  1. time :

    • time.time() 時間戳(獲取當前時間) 從1970-1-1 00:00 後走過的秒數
    • time.sleep(8) 等待的秒數
    import time
    now = time.localtime()
    print(now)
    print(now.tm_year) # 獲取當前時間的年份
    print(now.tm_mon)  # 獲取當前時間的月份
    print(now.tm_mday) # 獲取當前時間的幾號
  2. datetime

    • 獲取datetime格式時間

      import time
      from datetime import datetime,timezone,timedelta
      
      v1 = datetime.now()  # 獲取當前本地時間
      print(v1)            # 2019-04-18 16:39:31.802269
      
      tz = timezone(timedelta(hours=7)) #當前東7區時間  (如要獲取西7區時間 hours=-7)
      v2 = datetime.now(tz)
      print(v2)         #2019-04-18 15:39:31.802269+07:00   (中國在東8區,因此慢一個小時)
      
      v3 = datetime.utcnow()    #當前UTC時間(世界時間)
      print(v3)                 #2019-04-18 08:39:31.802269  (比中國時間慢8個小時)
    • 把datetime格式轉換成字符串 (strftime)

      import time
      from datetime import datetime,timezone,timedelta
      
      v1 = datetime.now()
      val = v1.strftime("%Y-%m-%d %H:%M:%S")  #(年-月-日 時:分:秒)
      print(val)    #2019-04-18 16:48:29
    • 字符串轉成datetime格式 datetime.strptime

      import time
      from datetime import datetime,timezone,timedelta
      
      v1 = datetime.strptime('2019-4-18','%Y-%m-%d')
      print(v1,type(v1))  # 2019-04-18 00:00:00 <class 'datetime.datetime'>
    • datetime時間的加減

      from datetime import datetime,timedelta
      
      v1 = datetime.strptime('2008-08-08','%Y-%m-%d')   
      v2 = v1-timedelta(days=150)   
      data = v2.strftime('%Y-%m-%d')
      print(data)  #2008-03-11
      
      #先轉換爲datetime格式進行加減,而後轉換爲字符串格式打印出來
    • 時間戳和datetime的關係

      import time
      from datetime import datetime,timezone,timedelta
      
      ctime = time.time()
      print(ctime)  # 1555578896.8276453
      v1 = datetime.fromtimestamp(ctime)
      print(v1) # 2019-04-18 17:14:56.827645
      
      v1 = datetime.now()
      val = v1.timestamp()
      print(val)  #1555579030.002739

8.第三方模塊: requests

import requests

# 獲取網頁源碼
ret = requests.get('一個網址 ').strip()   # 輸入網址後加一個空格

print(ret.content)  # 以字節的方式去顯示,中文顯示爲字符
print(ret.text)     # 以文本的方式去顯示

6.3異常處理

示例:
#寫函數去,接受一個列表。列表中都是url,請訪問每一個地址並獲取結果。
import requests 
def func(url_list):
    result = []
    try:
        for url in url_list:
            response = requests.get(url)
            result.append(response.text)
    except Exception as e:
        pass
    return result    #['http://www.baidu.com']  (中國沒法訪問谷歌)

def func2(url_list):
    result = []
    for url in url_list:
        try:
            response = requests.get(url)
            result.append(response.text)
        except Exception as e:
            pass
    return result   #['http://www.baidu.com','http://www.bing.com']

func(['http://www.baidu.com','http://www.google.com','http://www.bing.com'])

6.4 迭代器&生成器

  1. 迭代器
    • 優勢:節省內存。惰性機制。
    • 缺點:不直觀,速度相對慢,操做方法單一,不走回頭路。
  • 對某種對象(str/lsit/tuple/dict/set類建立的對象)中的元素進行逐一獲取,表象:具備__next__方法且每次調用都獲取可迭代對象中的元素
  • 列表轉換成迭代器
    • v1 = iter([1,2,3,4])
    • v2 = [1,2,3,4].__iter__()
  • 迭代器想要獲取每一個元素:反覆調用val = v1.__next__()
#示例:
v1 = "alex"
v2 = iter(v1)
while True:
     try:
        val = v2.__next__()
        
        
        print(val)
     except StopIteration as e:
        break
  • 直到報錯:StopIteration錯誤,表示迭代已經完畢

  • 如何判斷一個對象是不是迭代器 : 內部是否有__next__方法

  • for 循環

    v1 = [11,22,33,44]
    
    # 1.內部會將v1轉換成迭代器
    # 2.內部反覆執行 迭代器.__next__()
    # 3.取完不報錯
    for item in v1:
        print(item)
  • 可迭代對象

    • 內部具備_iter__方法且返回一個迭代器
    • 能夠被for 循環
    • 優勢:操做方法多,操做方法靈活,直觀
    • 缺點:佔用內存
  1. 生成器 (函數的變異)

    • 獲取生成器的三種方式

      • 生成器函數
      • 生成器表達式
      • python內部提供的一些
    • 生成器的本質就是迭代器,

      • 惟一區別:生成器是咱們本身用python代碼構建的數據結構,迭代器都是提供的或者是轉化得來的
    • 生成器函數 (內部是否包含yield)

      def func():
          print('F1')
          yield 1
          print('F2')
          yield 2
          print('F3')
      #函數內部代碼不會執行,返回一個生成器對象
      v1 = func()
      #生成器能夠被for 循環,一旦開始循環函數內部代碼就開始執行
      for item in v1:
          print(item)
      #  F1  1  F2  2  F3
      # yield from   優化了內層循環,提升了效率
      def func():
          l1 = [1, 2, 3, 4, 5]
          yield from l1
      ret = func()
      print(next(ret))  # 取列表裏的一個元素 1
      
      # yield
      def func():
          l1 = [1, 2, 3, 4, 5]
          yield l1
      ret = func()
      print(next(ret))  #獲得的是一個列表
    • 總結:

      • 函數中若是存在yield,那麼該函數就是一個生成器函數,調用生成器函數會返回一個生成器,生成器只有被for循環時,生成器函數內部代碼纔會執行,每次循環都會獲取yield返回的值
      • return:函數中只存在一個return結束函數,而且給函數的執行者返回值
      • yield:只要函數中有yield那麼他就是生成器函數了
      • 生成器函數能夠存在多個yield,yield不會結束生成器函數,一個yield對應一個next

第七章 : 面向對象


7.0 面向對象基礎

  • 什麼是類:具備相同方法和屬性的一類事物
  • 什麼是對象,實例:一個擁有具體屬性值和動做的具體個體
  • 實例化:從一個類獲得一個具體對象的過程
  • 類 ---> 實例化 ---> 對象
  • 類和對象的關係
    • 類是一個大範圍,是一個模子,約束了事物有哪些屬性,可是不能約束具體的值
    • 對象是一個具體的值,是模子的產物,遵循了類的約束,同時給屬性附上具體的值
  • 實例化所經歷的步驟:
    1. 類名() 以後的第一個事兒: 先開闢一塊內存空間
    2. 調用__init__ ,把空間的內存地址做爲self參數傳遞到函數內部
    3. 全部的這一個對象須要使用的屬性都須要和self關聯起來
    4. 執行完__init__中的邏輯以後,self變量會自動的被返回到調用處(發生實例化的地方)
  1. 應用場景:

    • 遇到不少函數,須要給函數進行歸類和劃分 [封裝]
  2. 基本格式

    class Person:
        def __init__(self,name,sex,job,age):
            self.name = name
            self.sex = sex
            self.job = job
            self.age = age
    obj = Person('alex','nan','IT','30')    # 實例化一個obj對象
    print(obj.__dict__)  # {'name': 'alex', 'sex': 'nan', 'job': 'IT', 'age': '30'}
    obj.name = 'wusir'  # 修改屬性
    obj.money = 1000    # 增長屬性
    del obj.money       # 刪除屬性
  3. 組合:

    • 一個類的對象是另外一個類對象的屬性

      # 查看linux57期的班級所學課程的價格
      # 查看python22期的班級所學課程的週期
      
      class Clas:
          def __init__(self,cname,begint,teacher,course):
              self.cname = cname
              self.begint = begint
              self.teacher = teacher
              self.course = course
      
      class Course:
          def __init__(self,name,period,price):
              self.name = name
              self.period = period
              self.price = price
      
      python = Course('python','6 months',21800)
      linux = Course('linux','5 months',19800)
      
      py22 = Clas('python全棧22期','2019-4-26','小白',python)
      linux57 = Clas('linux運維57期','2019-3-27','李導',linux)
      
      print(py22.course.period)
      print(linux57.course.price)
  4. 對象的做用

    • 存儲一些值,之後方便本身使用

      class File:
          def read(self):
              with open(self.xxx,mode= 'r',encoding = 'utf-8') as f:
                 data = f.read()
               return data             
      #實例化一個File 類的對象
      obj1 = File()
      #在對象中寫一個xxx = 'text.log'
      obj1.xxx = 'text.log'
      #經過對象調用類中的read方法,read方法中的self就是obj
      obj.read()
    • 總結:將數據封裝到對象,方便使用

總結:若是寫代碼時,函數比較多而亂

  • 1.能夠將函數歸類並放到同一類中

  • 2.函數若是有一個反覆使用的公共值,則能夠放到對象中

  • 練習

    #循環讓用戶輸入用戶名/密碼/郵箱.輸入完成後再進行打印
    
    class Person:
        def __init__(self,user,pwd,email):
            self.username = user
            self.password = pwd
            self.email = email
    
    user_lisr = []
    while Ture:
        user = input('輸入用戶名')
        pwd = input('請輸入密碼')
        email = input('請輸入郵箱')
        a = Person(user,pwd,email)
        user_list.append(a)
    for item in USER_LIST:
        temp = "個人名字:%s,密碼:%s,郵箱%s" %(item.username,item.password,item.email,)
        print(temp)

7.2 面向對象的三大特性

1.繼承

  • 何時才能用到繼承:
    • 多個類中若是有公共的方法,能夠放到基類中避免重複編寫
# 父類(基類)
class Base:
    def f1(self):
        pass
# 子類(派生類)
class Foo(Base):
    def f2(self):
        pass
      
# 建立一個子類的對象
obj = Foo()
# 執行對象.方法時,優先在本身的類中找,若是沒有就是父類中找。
obj.f2()
obj.f1()

# 建立了一個父類的對象
obj = Base()
obj.f1()
  • 繼承方法中的查找方法的順序

    • self 究竟是誰
    • self 是哪一個建立的,就像今後類開始找,本身沒有就找基類
  • 父類和子類方法的選擇

    • 子類的對象若是去調用方法,若是本身有就先調用本身的,本身沒有就用父類的,
    • 若是本身有還想用父類的:直接在子類的方法中調父類的方法 父類名.方法名(self)
  • 繼承的其餘現象

    1559547644541
    1559547683607

2.多態 (也叫鴨子模型)

  • 多態:一個類表現出的多種形態,其實是經過繼承來完成的

    '''
    若是狗類繼承動物類,貓類也繼承動物類
    那麼貓的對象也是動物類型的,狗的對象也是動物類型的
    在這個例子中,動物這個類型表現出了貓和狗的形態
    '''
# Python
def func(arg):
    v = arg[-1] # arg.append(9)
    print(v)
  • 什麼是鴨子模型?
    • 對於一個函數而言,python對於參數的類型不會限制,那麼傳入參數時就能夠是各類類型,在函數中若是有例如:arg.send方法,那麼就是對於傳入類型的一個限制(類型中必須有send方法).這就是鴨子模型,相似於上述的函數咱們認爲只要能呱呱叫的就是鴨子(只要有send方法,就是咱們想要的類型) -->wusir版
    • 在python中,一個類是否是屬於某一類型,不只能夠經過繼承來完成,還能夠是不繼承,可是若是這個類知足了某些類型的特徵條件,咱們就說他長得像這個類型,那麼他就是這個類型的鴨子模型 -->女神版

3.封裝

  • 廣義:把屬性的方法封裝起來,外面就不能直接調用了,要經過類的名字來調用

  • 狹義: 把屬性和方法藏起來,外面不能調用,只能在內部偷偷調用

    class User:
        def __init__(self,name,pwd):
            self.name = name
            self.__pwd = pwd    # 私有的實例變量 / 私有的對象屬性
    alex = User('alex',1234)
    print(alex.__pwd)  # 沒法訪問 報錯
    print(alex.pwd)    # 報錯
    
    '''
    給一個名字前面加上了雙下劃線的時候,這個名字就變成了一個私有的
    全部私有的內容或者名字都不能再類的外部調用只能在類的內部使用
    '''
    # 從外部調用加雙下劃線的方法或靜態變量
    class User:
        __country = 'china' # 私有的靜態變量
        __name = 'Alex'
        def func(self):
            print(self.__name) # 在類的內部使用的時候,自動把當前這句話所在的類的名字拼在私有變量前完成變形
    print(User._User__country)  # china
    User().func()  # Alex
    
    # __Country -->'_User__Country': 'China'
  • 私有的內容不能被子類使用

  • 其餘語言中的數據級別:

    • public 公有的:類內類外都能用,父類和子類都能用 python支持
    • protect 保護的:類內能使用,父類子類都能用,類外不能用 python不支持
    • private 私有的:本類的類內部能用,其餘地方不能用 python支持

7.1 成員

  1. 實例(對象)

    • 實例變量
    • 類變量
    • 綁定方法
    • 類方法
    • 靜態方法
    • 屬性
  2. 類變量

    1556087253366

    • 定義:
      • 寫在類的下一級,和方法同一級
    • 訪問
      • 類.類變量名稱
      • 對象.類變量名稱
    ####應用示例#####
    
    class Base:
        x = 1
    obj.Base()
    
    print(obj.x)   #先去對象中找,沒有再去類中找   1
    obj.y = 123    #在對象中添加了一個y=123的變量
    print(obj.y)   #對象中y=123   123
    obj.x = 123    #在對象中添加一個變量x=123   
    print(obj.x)   #   123
    print(Base.x)  #類中x=1   1
    • 總結
      • 找變量優先找本身,本身沒有找類或基類,修改或賦值只能在本身的內部設置
      • 類中的變量是靜態變量
      • 對象中的變量只屬於對象自己,每一個對象有屬於本身的空間來存儲對象的變量
      • 當使用對象名去調用某一個屬性的時候,會優先在本身的空間中尋找,找不到再去對應的類中尋找,若是類也沒有就報錯
  3. 方法(綁定方法)

    • 定義:至少有一個self參數

    • 執行:先建立對象, 對象.方法()執行

      class Foo:
          def __init__(self):
              self.name = 111
      
           def func(self,a,b)   #綁定方法,至少有一個self參數
             print(self.name,a,b)
      obj = Foo()
      obj.func(1,2)
  4. 靜態方法

    • 定義

      • @staticmethod裝飾器
      • 參數無限制
    • 執行

      • 類.靜態方法名()
      • 對象.靜態方法名 (不推薦)
      class Foo:
          def __init__(self):
              self.name = 123
      
          def func(self, a, b):
              print(self.name, a, b)
      
          @staticmethod
          def f1():      #靜態方法(能夠不用傳參數)
              print(123)
      
      obj = Foo()
      obj.func(1, 2)
      
      Foo.f1()
      obj.f1() # 不推薦
  5. 類方法

    • 定義:

      • @classmethod裝飾器
      • 至少有一個cls參數,當前類
    • 執行:

      • 類.類方法名()
      • 對象.類方法名() 不推薦
      class Goods:
          __discount = 0.8
          def __init__(self):
              self.__price = 5
              self.price = self.__price * self.__discount
          @classmethod   # 把一個對象的綁定方法修改爲一個類方法
          def change_discount(cls,new_discount):
              cls.__discount = new_discount
      
      Goods.change_discount(0.6)   # 類方法能夠經過類名來調用
      obj1 = Goods()
      print(obj1.price)    #  3.0
      
      obj1.change_discount(0.5)   # 類方法能夠經過對象來調用
      obj2 = Goods()
      print(obj2.price)    # 2.5
      
      #############  示例:
      import time
      class Date:
          def __init__(self,year,month,day):
              self.year = year
              self.month = month
              self.day = day
      
          @classmethod
          def today(cls):
              now_time = time.localtime()
              date = cls(now_time.tm_year,now_time.tm_mon,now_time.tm_mday)
              return date
      date = Date.today()
      print(date.year)
      print(date.month)
      print(date.day)
      # 問題: @classmethod和@staticmethod的區別?
      '''
      一個是類方法,一個是靜態方法
      定義:
         類方法:用@classmethod作裝飾器且至少有一個cls參數
         靜態方法:用@staticmethod作裝飾器且參數無限制
      調用:
      類.方法()直接調用
      對象.方法()也可調用  (不推薦)
      '''
  6. 屬性

    • 定義:

      • @property裝飾器:把一個方法假裝成一個屬性,在調用這個方法的時候不須要加()就能夠直接的獲得返回值
      • 只有一個self參數
    • 執行:

      • 對象.方法 不加括號
      class Foo:
      
          @property
          def func(self):
              print(123)
              return 666
      
      obj = Foo()
      result = obj.func
      print(result)
      # property進階
      class Goods:
          discount = 0.8
          def __init__(self,name,origin_price):
              self.name = name
              self.__price = origin_price
          @property
          def price(self):
              return self.__price * self.discount
      
          @price.setter
          def price(self,new_value):
              if isinstance(new_value,int):
                  self.__price = new_value
      
      apple = Goods('apple',5)
      print(apple.price)   # 調用的是被@property裝飾的price
      apple.price = 10     # 調用的是被setter裝飾的price
      print(apple.price)
    • 屬性的應用

      '''
      分頁並查看頁碼中的內容
      '''
      
      class Page:
          def __init__(self, total_count, current_page, per_page_count=10):
              self.total_count = total_count
              self.per_page_count = per_page_count
              self.current_page = current_page
          @property
          def start_index(self):
              return (self.current_page - 1) * self.per_page_count
          @property
          def end_index(self):
              return self.current_page * self.per_page_count
      
      
      USER_LIST = []
      for i in range(321):
          USER_LIST.append('alex-%s' % (i,))
      
      # 請實現分頁展現:
      current_page = int(input('請輸入要查看的頁碼:'))
      p = Page(321, current_page)
      data_list = USER_LIST[p.start_index:p.end_index]
      for item in data_list:
          print(item)
  • 新式類 / 經典類

    class Foo:
        pass
    
    class Foo(object):
        pass
    
    #在py3中這兩個的寫法是同樣的,由於全部的類默認都會繼承object類,所有都是新式類
    
    # 若是在python2中這樣定義,則稱其爲:經典類
    class Foo:
        pass 
    # 若是在python2中這樣定義,則稱其爲:新式類
    class Foo(object):
        pass 
    '''
    新式類和經典類的區別:
    新式類:繼承object ,有super mro ,繼承廣度優先
        查看廣度優先的順序: 類名.mro()
    
    經典類:不繼承object,沒有super mro ,繼承深度優先
    '''

7.3 雙 __ 方法

  • __init__ 初始化方法

  • __new__ 用於建立空對象(構建方法)

    class A:
        def __new__(cls, *args, **kwargs):
            obj = super().__new__(cls)
            # obj = object.__new__(cls)  # 第二種寫法
            print('執行new方法')
            return obj  # 須要將對象返回回去,才能執行init方法
        def __init__(self):
            print('執行init方法')
    A() 
    先打印: 執行new方法  再打印: 執行init方法
    
    # 實例化的時候:
      先建立一個對象的空間,有一個指針指向類 --> __new__
        調用init --> __init__
  • __call__ 對象加括號,執行cal方法

    格式:

    class A:
        def __call__(self, *args, **kwargs):
            print('*********')
    
    obj = A()
    print(callable(obj))  # 判斷對象是不是可被調用的,若是類中沒有call方法,則是False
    A()()   # 對象加() 會自動執行call方法裏面的代碼 
    
      運行結果:  True
                *********
  • __getitem__ __setitem__ __delitem__

    class Foo(object):
    
        def __setitem__(self, key, value):
            print(key,value)
    
        def __getitem__(self, item):
            return item + 'uuu'
    
        def __delitem__(self, key):
            pass
    
    obj1 = Foo()
    obj1['k1'] = 123  # 內部會自動調用 __setitem__方法   #打印的結果爲  k1 123 
    val = obj1['xxx']  # 內部會自動調用 __getitem__方法
    print(val)   # 打印結果爲 xxxuuu
    del obj1['ttt']  # 內部會自動調用 __delitem__ 方法
  • __str____repr__

    • 當咱們打印一個對象 用%s進行字符串拼接或者str(對象)老是調用這個對象的__str__方法
    • 若是找不到__str__ ,就調用 __repr__ 方法
    • __repr__ 不只僅是 __str__ 的替代品,還有本身的功能
    • 用%r 進行字符串拼接 或者用repr(對象)的時候老是調用這個對象的__repr__ 方法
    class clas:
        def __init__(self):
            self.student = []
        def append(self,name):
            self.student.append(name)
        def __repr__(self):
            return str(self.student)
        def __str__(self):
            return 'aaa'
    
    py22 = clas()
    py22.append('大壯')
    print(py22)  #  aaa
    print(str(py22))   # aaa
    print('咱們py22班 %s'%py22)   # 咱們py22班 aaa
    print('咱們py22班 %r'%py22)   # 咱們py22班 ['大壯']
    print(repr(py22))   # ['大壯']
  • __dict__

    class Foo(object):
        def __init__(self,name,age,email):
            self.name = name
            self.age = age
            self.email = email
    
    obj = Foo('alex',19,'xxxx@qq.com')
    val = obj.__dict__ # 去對象中找到全部變量並將其轉換爲字典
    print(val)
  • 上下文管理

    class Context:
        def __enter__(self):
            print('進入')
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('推出')
    
        def do_something(self):
            print('內部執行')
    
    with Context() as ctx:
        print('內部執行')
        ctx.do_something()
    
    # 當語法有 with 類() 時,類裏面必須包含__enter__方法和__exit__方法;方法__enter__返回的是什麼,as後面接收就是什麼
  • __len__

    class Cls:
        def __init__(self,name):
            self.name = name
            self.students = []
        def len(self):
            return len(self.students)
        def __len__(self):
            return len(self.students)
    py22 = Cls('py22')
    py22.students.append('杜相璽')
    py22.students.append('莊博')
    py22.students.append('大壯')
    print(py22.len())  # 3
    print(len(py22))   # 3
    
    # py22.len() 調用的是def len 
    # len(py22)  調用的是def __len__
  • __base__ 查看類繼承了哪個類

  • 兩個對象的相加

    class Foo(object):
        def __add__(self, other):
            return 123
    
    obj1 = Foo()
    obj2 = Foo()
    val  = obj1 + obj2
    print(val)obj1 = Foo()
    obj2 = Foo()
    val  = obj1 + obj2
    print(val)
  • __eq__ __gt__ __lt__

    class Person(object):
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def __eq__(self,other):  # 兩個對象做比較的時候,會自動調用這個方法
          print('in eq')
        def __gt__(self,other):
            print('in gt')
        def __lt__(self,other):
            print('in lt')
    
    alex = Person('alex',83)
    wusir = Person('wusir',74)
    
    alex == wusir # == 符號恰好會調用alex對象對應類的__eq__方法,wusir會被當作other參數傳入方法
    alex < wusir  # 執行__gt__方法
    alex > wusir  # 執行__lt__方法

特殊成員:就是爲了能快速實現執行某些方法而生

7,4 內置函數補充

  1. type:查看類型

    class Foo:
        pass
    
    obj = Foo()
    
    if type(obj) == Foo:
        print('obj是Foo類的對象')
    
    # 判斷obj是不是foo的對象
  2. issubclass 判斷是不是某個類的基類

    class Base:
        pass
    
    class Base1(Base):
        pass
    
    class Foo(Base1):
        pass
    
    class Bar:
        pass
    
    print(issubclass(Bar,Base))   # false
    print(issubclass(Foo,Base))   # true
  3. isinstance 判斷對象是不是某個類或其基類的實例對象

    class Base(object):
        pass
    
    class Foo(Base):
        pass
    
    obj = Foo()
    
    print(isinstance(obj,Foo))  # 判斷obj是不是Foo類或其基類的實例(對象)
    # True
    print(isinstance(obj,Base)) # 判斷obj是不是Foo類或其基類的實例(對象)
    # True
  4. super

    class A(object):
        def func(self):
            print('A')
    class B(A):
        def func(self):
            super().func()
            print('B')
    class C(A):
        def func(self):
            super().func()
            print('C')
    class D(B,C):
        def func(self):
            super().func()
            super(D,self).func()
            print('D')
    D().func()
    # 結果: A C B D
    '''
    super 是按照mro順序(D-->B-->C--A)來尋找當前類的下一個類
    在D類中的super還能夠寫成: super(D,self).func(),py2中的新式類必須這樣寫
    '''
    
    # 示例:
    class User:
        def __init__(self,name):
            self.name = name
    class VIPUser(User):
        def __init__(self,name,level,strat_date,end_date):
            # User.__init__(self,name)
            super().__init__(name)   # 推薦的
            # super(VIPUser,self).__init__(name)
            self.level = level
            self.strat_date = strat_date
            self.end_date = end_date
    
    太白 = VIPUser('太白',6,'2019-01-01','2020-01-01')
    print(太白.__dict__)
  • 結論:
    • 在py3中不須要傳參數,自動就幫咱們尋找當前類的mro順序的下一個類中的同名中方法
    • 在py2中的新式類中,須要咱們主動傳遞參數super(子類的名字,子類的對象).函數名()

7.5 異常處理

  • 基本格式

    try:
        pass
    except Exception as e:   # Exception : 全部報錯信息都能接收
        pass

    finally:

    try:
        int('asdf')
    except Exception as e:
        print(e)  # e是Exception類的對象,中有一個錯誤信息。
    finally:
        print('最後不管對錯都會執行')
    # #################### 特殊狀況 #########################
    def func():
        try:
            # v = 1
            # return 123
            int('asdf')
        except Exception as e:
            print(e)  # e是Exception類的對象,中有一個錯誤信息。
            return 123   
        finally:
            print('最後')
    func()
    #函數中有return時,finally也會執行
  • 主動觸發異常

    try:
        int('123')
        raise Exception('xxxxx') # 代碼中主動拋出異常
    except Exception as e:
        print(e)   
    # 打印的結果是Exception括號內拋出的異常
  • 自定義異常

    class MyException(Exception):
        pass
    
    try:
        raise MyException('asdf')
    except MyException as e:
        print(e)
    class MyException(Exception):
        def __init__(self,message):
            super().__init__()
            self.message = message
    
    try:
        raise MyException('asdf')
    except MyException as e:
        print(e.message)

7.6 可迭代對象

  • 表象:能夠被for循環對象就能夠成爲是可迭代對象

    class Foo:
        pass
    
    obj = Foo()
  • 如何讓一個對象變成可迭代對象

    • 在類中實現__iter__方法且返回一個迭代器(生成器)
    class Foo:
        def __iter__(self):
            return iter([1,2,3,4])
    
    obj = Foo()
    
    class Foo:
        def __iter__(self):
            yield 1
            yield 2
            yield 3
    
    obj = Foo()
  • 只要能被for循環就是去看他內部的iter方法

7.7 約束

import sys
class Payment:   # 這個類爲抽象類,爲了規範子類必須實現的父類的同名方法
    def pay(self,money): # 須要傳參
        raise NotImplementedError('請在子類中重寫pay方法')   # 主動拋出異常

class Wechat(Payment):
    def __init__(self,name):
        self.name = name
    def pay(self,money):
        print('%s經過微信支付%s錢成功' %(self.name,money))

class Apple(Payment):
    def __init__(self,name):
        self.name = name
    def pay(self,money):    #  經過繼承的關係來判斷方法名是否同樣,若是與歸一化設計的方法不一樣則會拋出異常
        print(print('%s經過蘋果支付%s錢成功' % (self.name, money)))

# 歸一化設計
def pay(name,price,kind):
    class_name = getattr(sys.moudles[__name__],'kind')   # 經過反射獲得類的名字
    obj = class_name(name)
    obj.pay(price)
    
pay('alex',200,'Wechat')
pay('alex',200,'Apple')

########## 另外一種方式:約束力強,依賴abc模塊
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self,money): pass
        '''只要你見到了項目中有這種類,你要知道你的子類中必須實現和pay同名的方法'''

7.8 反射

  • 概念 : 根據字符串的形式去某個對象中操做他的成員

  • getattr(對象,'字符串') 根據字符串的形式去某個對象中獲取對象的成員

    • 獲取類中的屬性

      class Foo(object):
          def __init__(self,name):
              self.name = name 
          def func(self):
              print(123)
      obj = Foo('alex')
      # 獲取變量
      v1 = getattr(obj,'name')
      print(v1)    # alex
      
      getattr(obj,'func')()  # 123
    • 獲取當前py文件中的屬性

      import sys
      def func():
          print(123)
      name = 'alex'
      
      getattr(sys.modules[__name__],'func')           # 123
      print(getattr(sys.modules[__name__]),'name')  # alex
    • 引用模塊中的任意的變量

      # a.py 中的屬性有:
          def func():
              print('in func')
          name = 'alex'
          class User: pass
          obj = User()
      
      # 運行腳本的文件  
      import a
      getattr(a,'func')()  # in func
      getattr(a,'obj')     # 獲得地址
      print(getattr(a,'name'))  # alex
  • hasattr(對象,'字符串') 根據字符串的形式去某個對象中判斷是否有該成員

    class A:
        job = 'IT'
        def __init__(self):
            self.name = 'alex'
            self.age = 83
        def func(self):
            print('in func')
    
    a = A()
    
    print(hasattr(a,'sex'))    # False
    print(hasattr(a,'func'))   # True
    if hasattr(a,'func'):
        if callable(getattr(a,'func')):  # 判斷這個函數是否可被調用
            getattr(a,'func')()  # in func
  • setattr(對象,"變量","值") 根據字符串的形式去某個對象中設置成員

    class Foo:
        pass
    obj = Foo()
    obj.k1 = 999
    setattr(obj,'k1',123) # obj.k1 = 123
    
    print(obj.k1)   # 123
  • delattr(對象,"變量") 根據字符串的形式去某個對象中刪除成員

    class Foo:
        pass
    
    obj = Foo()
    obj.k1 = 999
    delattr(obj,'k1')
    print(obj.k1)
  • 經常使用操做

    class User:
        lis = [('登入','login'),
               ('註冊','register'),
               ('刪除文件','remove'),
               ('複製文件','copy')]
        def login(self):
            print('in login')
        def register(self):
            print('in register')
        def remove(self):
            print('in remove')
        def copy(self):
            print('in copy')
    
    obj = User()
    for index,item in enumerate(obj.lis,1):
        print(index,item[0])
    while True:
        num = input('請選擇要操做的序號:')
        if num.isdecimal() and 0 < int(num) <= len(obj.lis):
            if hasattr(obj,obj.lis[int(num)-1][1]):
                getattr(obj,obj.lis[int(num)-1][1])()
        else: print('輸入有誤')

7.9 模塊: importlib

# from utils import redis
import importlib

middleware_classes = [
    'utils.redis.Redis',
    # 'utils.mysql.MySQL',
    'utils.mongo.Mongo'
]
for path in middleware_classes:
    module_path,class_name = path.rsplit('.',maxsplit=1)
    module_object = importlib.import_module(module_path)# from utils import redis
    cls = getattr(module_object,class_name)
    obj = cls()
    obj.connect()


# # 用字符串的形式導入模塊。
# redis = importlib.import_module('utils.redis')
#
# # 用字符串的形式去對象(模塊)找到他的成員。
# getattr(redis,'func')()

7.9.1 字符串格式化

  • 幾種表達形式

    mes = '我是%s,年齡%s' %('Alex',99,)
    mes = '我是%(n1)s,年齡%(n2)s' %('n1':'Alex','n2':99)
    
    # v1 = "我是{0},年齡{1}".format('alex',19) 
    v1 = "我是{0},年齡{1}".format(*('alex',19,)) print(v1)
    
    # v2 = "我是{name},年齡{age}".format(name='alex',age=18) 
    v2 = "我是{name},年齡{age}".format(**{'name':'alex','age':18})
    print(v2)

7.9.2 有序字典

from collections import orderedDict  #導入模塊將其轉換爲有序字典

info = OrderDict()
info['k1'] = 123
info['k2'] = 456

print(info.keys()) 
print(info.values()) 
print(info.items())

7.9.3 棧和隊列

  • 繼承實現棧和隊列
class Foo:
    def __init__(self):
        self.l = []
    def put(self,num):
        self.l.append(num)
        return self.l
        
class Queue(Foo):   # 隊列: 先進先出
    def get(self):
        return self.l.pop(0)

class Stack(Foo):    # 棧: 後進先出
    def get(self):
        return  self.l.pop()

7.9.2 單例模式

  • 不管實例化多少次,永遠用的都是第一次實例化出對象

  • 單例模式標準

    #方法一
    class Singleton:
        def __new__(cls,*args,**kwargs):
            if not hasattr(cls,'__instance'):
                cls.__instance = object.__new__(cls)
            return cls.__instance
    
    one = Singleton()
    two = Singleton()
    # 二者的內存地址徹底同樣
    #方法二
    class Baby:
        __instance = None
        def __new__(cls, *args, **kwargs):
            if cls.__instance is None:
                cls.__instance = super().__new__(cls)
            return cls.__instance
        def __init__(self,cloth,pants):
            self.cloth = cloth
            self.pants = pants
    b1 = Baby('紅毛衣','綠皮褲')
    print(b1.cloth)
    b2 = Baby('白襯衫','黑豹紋')
    print(b1.cloth)
    print(b2.cloth)

7.9.3 日誌 (模塊logging)

  • 日誌處理本質; Logger / FileHandler / Formatter

  • 日誌的做用:

    • 用來記錄用戶的行爲--> 數據分析
    • 用來記錄用戶的行爲--> 操做審計
    • 排查代碼的錯誤
  • 輸出內容是有等級的: 默認處理warning級別及其以上的全部信息

    logging.debug('debug message')          # 調試
    logging.info('info message')            # 信息
    logging.warning('warning message')      # 警告
    logging.error('error message')          # 錯誤
    logging.critical('critical message')    # 批判性的
    
    '''
    不管但願日誌打印那些內容,都是本身寫的,沒有自動生成日誌這種事
    '''
  • 將日誌輸出到屏幕

    logging.basicConfig(
        format='%(asctime)s - %(name)s - %(levelname)s[line :%(lineno)d]-%(module)s:  %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S ',
    )
    logging.warning('warning message test2')
    logging.error('error message test2')
    logging.critical('critical message test2')
  • 輸出到文件,而且設置信息的等級,寫入文件會出現亂碼問題

    logging.basicConfig(
        format='%(asctime)s - %(name)s - %(levelname)s[line :%(lineno)d]-%(module)s:  %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S %p',
        filename='tmp.log',     # 將日誌文件寫入到名爲tmp.log的文件中,以append的方式追加進去
        level= logging.DEBUG    # 設置最低處理等級爲DEBUG,等級必須大寫
    )
    logging.debug('debug 信息錯誤 test2')
    logging.info('warning 信息錯誤 test2')
    logging.warning('warning message test2')
    logging.error('error message test2')
    logging.critical('critical message test2')
  • 同時向文件和屏幕上輸出,並解決亂碼問題 (經常使用這種方式處理日誌)

    fh = logging.FileHandler('tmp.log',encoding='utf-8')  # 向文件輸出並處理亂碼問題
    # fh2 = logging.FileHandler('tmp2.log',encoding='utf-8') # 也可同時輸出到兩個文件
    sh = logging.StreamHandler()  # 輸出到屏幕
    logging.basicConfig(
        format='%(asctime)s - %(name)s - %(levelname)s[line :%(lineno)d]-%(module)s:  %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S %p',
        level= logging.DEBUG,  # 設置最低處理等級爲DEBUG,等級必須大寫
        # handlers=[fh,sh,fh2]
        handlers=[fh,sh]       # 將須要輸出到的內容添加到handlers
    )
    logging.debug('debug 信息錯誤 test2')
    logging.info('warning 信息錯誤 test2')
    logging.warning('warning message test2')
    logging.error('error message test2')
    logging.critical('critical message test2')
  • 作日誌的切分

    import time
    from logging import handlers
    sh = logging.StreamHandler()
    rh = handlers.RotatingFileHandler('myapp.log', maxBytes=1024,backupCount=5)   # 按照大小作切割
    fh = handlers.TimedRotatingFileHandler(filename='x2.log', when='s', interval=5, encoding='utf-8')
    logging.basicConfig(
        format='%(asctime)s - %(name)s - %(levelname)s[line :%(lineno)d]-%(module)s:  %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S %p',
        level= logging.DEBUG,
        handlers=[fh,rh,sh]
    )
    for i in range(1,10):
        time.sleep(1)
        logging.error('KeyboardInterrupt error %s'%str(i))

7.9.4 項目結構目錄

相關文章
相關標籤/搜索