Python零基礎入門學習筆記

2020-10-20 12:00:57

Python 基礎入門學習

一.基本語句

  1. 註釋# 單行註釋 """多行註釋 """

  2. print (" ") 輸出函數

  3. 基本運運算元: + - * / //(取整) %(取餘) **(冪運算)

  4. 變數的定義: 變數名 = 值 (每個變數使用前都必須賦值,變數在賦值以後才會被創造,定義時不需要指定變數型別)

  5. type( ) 檢視變數型別函數

  6. input( ) 變數輸入函數 用法舉例: a = input(「輸入數位:」) 輸入的任何內容的資料型別預設為字元型str

  7. int(a) float(b) 型別轉換函數,將a轉換為int型,將b轉換為float型

  8. 格式化輸出

    print("格式化字串" % 變數1)

    print("格式化字串" % (變數1,變數2...))

    (%s - 字串)

    (%d - 帶符號十進位制整數——%06d表示輸出六位數,不足地方用0補全)

    (%f - 浮點數——%.02f表示小數點後顯示兩位)

    (%% - 輸出%)

  9. f-格式化字串: print(f’ My name is {name} ')

  10. 跳脫字元\n 換行 \t 製表符 : 1個tab鍵(4個空格)

  11. 結束符:python中的 print 預設以 \n 為結束符,即預設換行,但可自己設定,如: print('hello', end="\t")

  12. 識別符號 由字母數位下劃線組成,不能以數位開頭,不能與關鍵詞重名。識別符號區分大小寫,命名規則推薦多個單詞時全部小寫並將每個單詞用下劃線隔開。

  13. if語句: 在Python開發中,Tab和空格一定不能混用!

    if 條件1:
    
        條件1成立時要執行的程式碼
    
    elif 條件2:
        
        條件2成立時要執行的程式碼
    
    else:
        
        條件12都不成立時執行的程式碼
    
  14. if語句訓練:猜拳遊戲

    #if-elif-else訓練: 猜拳遊戲
    
    
    import random
    
    player = int(input('請出拳 (0-拳頭 1-剪刀 2-布):'))
    computer = random.randint(0,2)
    
    #平局
    if player == computer:
        print('平局')
    #電腦勝
    elif ( ((player == 0) and (computer == 2)) or ((player == 1)and(computer == 0)) or ((player == 2)and(computer == 1)) ):
        print('電腦贏了!你個睿智!你連電腦都打不過!')
    #玩家勝
    else:
        print('你贏了!不容易不容易啊!')
    
  15. 亂數的實現:

    匯入 random 模組,使用 randint (隨機整數) 功 如:

    import random
    
    num = random.randint(0,2) 
    

    ​ (num為0、1、2中的隨機一個數)

  16. 三目運運算元:

    條件成立時的表示式 if 條件 else 條件不成立時的表示式 
    

    如: MaxNum = a if a>b else b

  17. While 迴圈:

    while 條件:
    
        條件成立時重複執行的程式碼
    

    注意: 計數的初始值習慣寫為0

  18. break 和 continue :

    break終止迴圈,即不再回圈

    continue 為退出當前一次迴圈而直接執行下一次迴圈,即跳入下一次迴圈

  19. for 迴圈:

    for 臨時變數 in 序列:
        
        重複執行的程式碼
    
  20. while 與 else : 如果迴圈由 break 停止,則else下的程式碼不執行,for 與 else 的用法與此類似

    while 條件:
    
        條件成立時重複執行的程式碼
    
    else:
    
        迴圈正常結束之後執行的程式碼
    

二.基本資料型別

  1. 字串可以用單引號、雙引號、三引號括起來,字串為不可變型別

  2. python中每個字串自帶下標和索引,可用 str[x] 來精確存取字串 str 中的某個字元

  3. 切片: 指對 字串列表元組 進行擷取其中一部分的操作

    語法: 序列[開始位置下標 : 結束位置下標 : 步長]

    其中切片不包含結束位置下標對應的資料 ,即開始位置下標和結束位置下標為 [ ) 的包含形式

    下標 和 步長 均可不寫或寫負數,步長預設為1,若下標開始到結束的方向與步長的方向衝突,則無法選取出資料

  4. 字串的查詢: find() 、index() 、count() 、rfind() 、rindex()

    find() : 檢測某個子串是否包含在這個字串中,如果存在則返回這個子串開始位置的下標,否則返回-1

    字串序列.find( 子串 , 開始位置下標 , 結束位置下標 )
    

    開始和結束位置下標可以省略,表示在整個字串序列中查詢

    index() : 與find()函數的用法一樣,但如果不存在要查詢的子串,則會報錯

    count() :返回某子串在該字串中出現的次數,若不存在則返回0

    rfind()rindex() 查詢方向為從右側開始,其功能與 find() 與 index() 相同

  5. 字串的替換replace() 替換

    字串序列.replace ( 舊子串、新子串、替換次數 )
    

    注意: replace函數並不會改變原有字串的資料,修改後的資料是replace函數的返回值

  6. 字串的分割split() 分割,返回一個列表,丟失分割字元

    字串序列.split(分割字元,分割次數)
    

    注意:split函數也不會改變原有字串資料,修改後的資料為函數返回值

  7. 列表的合併join() 合併,返回一個字串,新增連線字元

    連線字串.join(多字串組成的列表)
    

    注意: join() 合併 是 split() 分割 的逆序操作

  8. 字串修改大小寫函數

    capitalize() 將字串第一個字母轉換為大寫,其餘均為小寫

    title() 將字串中每個單詞的首字母轉化成大寫,其餘均為小寫

    lower() 將字串中的大寫全部轉換為小寫

    upper() 將字串中的小寫全部轉換為大寫

    例:

    initial: brotheR aNd me
    capitalize: Brother and me
    title: Brother And Me
    lower: brother and me
    upper: BROTHER AND ME

  9. 字串刪除空白字元函數

    lstrip() : 刪除字串左側空白字元

    rstrip() : 刪除字串右側空白字元

    strip() : 刪除字串兩側空白字元

    例:

    initial: " brother and me "
    lstrip: 「brother and me "
    rstrip: " brother and me」
    strip: 「brother and me」

  10. 字串對齊函數: ljust() 、 rjust() 、center()

    返回 一個原字串 左/右/中 對齊,並用指定字元(預設空格)填充至對應長度的新字串

    字串序列.ljust( 長度 , 填充字元 ) 
    
    字串序列.rjust( 長度 , 填充字元 ) 
    
    字串序列.center( 長度 , 填充字元 ) 
    

    例:

    initial: brother and me
    ljust: brother and me----------------
    rjust: ----------------brother and me
    center: --------brother and me--------

  11. 字串判斷開頭或結尾函數

    startswith() : 檢查字串是否以指定子串開頭,是則返回True,否則返回False。如果設定開始和結束位置下標,則在指定範圍內檢查

    字串序列.startswith(子串,開始位置下標,結束位置下標)
    

    endswith() : 檢查字串是否以指定子串結尾,用法與 startswith()相同

    字串序列.endswith(子串,開始位置下標,結束位置下標)
    
  12. 字串字元型別判斷函數

    isalpha() : 如果字串非空且只包含字母則返回True , 否則返回False

    isdigit() : 如果字串非空且只包含數位則返回True , 否則返回False

    isalnum() : 如果字串非空且只包含數位或字母則返回True, 否則返回False

    isspace() : 如果字串非空且只包含空格則返回True , 否則返回False

  13. 列表 : 可以用下標選取指定資料,列表為可變型別

  14. 列表資料查詢函數

    index() : 返回指定資料所在位置的下標,若資料不存在則報錯

    列表序列.index(資料, 開始位置下標, 結束位置下標)
    

    count() : 返回指定資料在該列表出現的次數,若資料不存在則返回0

    列表序列.count(資料)
    

    len() : 返回列表的長度,即列表中資料的個數

    len(列表序列)
    
  15. 判斷列表中是否存在指定資料

    in : 判斷指定資料在某個序列的存在,存在返回True,否則返回False

    '指定資料' in 列表序列
    

    not in : 與 in 的用法相同,返回結果相反

  16. 列表資料增加函數

    append() : 列表結尾追加資料,若資料為一個序列,則直接追加整個序列到列表的結尾位置

    列表序列.append(資料)
    

    extend() : 列表結尾追加資料,若資料為一個序列,則將序列的資料逐一新增到列表,若資料為字串,則將單獨的每個字元逐一新增到列表

    列表序列.extend(資料)
    

    insert() : 指定位置新增資料,增添方式與 append() 相同

    列表序列.insert(位置下表,資料)
    
  17. 列表資料刪除函數

    del 目標(列表名 或 列表指定下標資料)

    pop() : 刪除指定下標的資料(預設為最後一個),並返回該資料。

    列表序列.pop(下標)
    

    remove() : 移除列表中某個資料的第一個匹配項,若匹配失敗則報錯

    列表序列.remove(資料)
    

    clear() : 清空列表中的所有資料

    列表序列.clear()
    
  18. 列表資料修改函數

    修改指定下標資料列表序列[下標] = 資料

    reverse() : 將列表資料的順序逆置

    列表序列.reverse()
    

    sort() : 對列表的資料進行排序

    列表序列.sort( key = None, reverse = False)
    

    注意: reverse = True 降序 reverse = False 升序(預設)

  19. 列表資料複製函數

    copy() : 列表資料複製

    新列表序列 = 原列表序列.copy()  
    

    即將原列表的資料複製到新列表中

  20. 列表的迴圈遍歷

    while迴圈方法 :

    i = 0
    
    while i < len(list):
    
        print(list[i])
    
        i += 1
    

    for迴圈方法 :

    for i in list:
    
        print(i)
    
  21. 列表巢狀:指一個列表裡包含了其他的子列表。

    List = [ ['a' , 'b' , 'c'] , ['1' , '2' , '3'] , ['&' , '$' , '%'] ]

  22. 列表綜合訓練

    #將8位元老師隨機分配到3個辦公室中
    import random
    teacher = ['a1','a2','a3','a4','a5','a6','a7','a8']
    room = [[],[],[]]
    for i in teacher:
        n = random.randint(0,2)
        room[n].append(i)
    print(room)
    
    i = 1
    for r in room:
        print(f'辦公室{i}的人數是{len(r)},他們分別為:',end = '\t')
        for name in r:
            print(name,end = '\t')
        print()
        i += 1
    
  23. 元組: 一個元組可以儲存多個資料(與列表相同),但元組內的資料是不能修改的。

    元組名 (資料1 , 資料2 , 資料3)

    注意: 如果定義的元組只有一個資料,那麼需要新增逗號,湊則資料型別為該資料型別,而不是 元組(tuple) 資料型別,如 tuple = (‘x’ , )

  24. 元組的常見操作

    按下標查詢資料 : 如tuple1[0] 、 tuple1[1]等

    index() : 查詢某個資料,用法與字串、列表的index相同

    count() : 統計某個資料在當前元組出現的次數

    len() : 統計元組中的資料個數

  25. 元組資料的修改

    元組內的直接資料如果修改則立即報錯

    如果元組裡面有列表,可直接修改列表內的資料,如 (‘abc’ , ‘qwe’ , [‘123’ , ‘456’ , ‘789’] , ‘jkl’) 元組就可以修改其中的 ‘123’ , ‘456’ , ‘789’ 資料

  26. 字典:字典裡的資料是以鍵值對形式儲存的。字典為可變型別

    特點: 符號為大括號,資料為鍵值對形式出現,各個鍵值對之間用逗號隔開

    dict1 = { '鍵1' : '值1' , '鍵2' : '值2' , '鍵3' : '值3' }
    

    空字典除了可以用空大括號建立,也可以用函數建立: dict2 = dict()

  27. 字典常見操作

    增 / 改字典序列[‘key’] = 值

    注意: 如果key存在則修改該鍵對應的值,如果key不存在則新增此鍵值對

    del(dict) 刪除字典

    del dict['Key'] 刪除字典中指定鍵值對

    dict.clear() 清空字典

    按key值寫法直接查詢字典序列[‘鍵’]

    按函數寫法查詢: get() keys() values() items()

    get() : 獲取某個鍵對應的值

    字典序列.get(key , 預設值)
    

    注意:若當前查詢的key不存在則返回預設值,若預設值省略不寫則返回None

    keys() : 獲取字典中所有的key,並返回可迭代物件

    字典序列.keys()
    

    values() : 獲取字典中所有的values,並返回可迭代物件

    字典序列.values()
    

    items() : 獲取字典中所有的鍵值對(key 和 values),並返回可迭代物件 ,裡面的資料是元組

    字典序列.items()
    
  28. 字典的迴圈遍歷

    遍歷字典的Key

    for key in dict1.keys():    
        print(key)
    

    遍歷字典的Value

    for value in dict1.values():    
        print(value)
    

    遍歷字典的元素

    for item in dict1.items():    
        print(item)
    

    遍歷字典的鍵值對(拆包)

    for key, value in dict1.items():
        print(f'{key} = {value}')
    
  29. 集合: 建立集合可使用 {} 或 set() ,但是如果要建立空集合只能使用 set() , 因為使用 {} 會建立空字典。

    集合資料特點: 集合裡面的資料會自動去重,不允許重複;集合裡面的資料沒有順序,且不支援下標。集合是可變型別

  30. 集合的建立

    直接建立: s1 = {10 , 20 , 30 , 40 , 50}

    使用set()建立: s2 = set('brother')

    建立空集合: s3 = set()

  31. 集合中資料的常見操作

    增加資料: add() update()

    集合.add(資料) 增加單個資料,要增加的資料在原集合中存在的話,不進行任何操作

    集合.update(資料列表) 在集合中增加資料序列

    刪除資料: remove() discard() pop()

    集合.remove(資料) 刪除集合中的指定資料,如果資料不存在則會報錯

    集合.discard(資料) 刪除集合中的指定資料,如果資料不存在也不會報錯

    集合.pop() 隨即刪除集合中的某個資料,並返回這個資料

    查詢資料: in 判斷資料在集合序列 not in 判斷資料不在集合序列

  32. 公共操作:運運算元、公共方法、容器型別轉換

    運運算元:

    + 合併,支援字串、列表、元組

    * 複製,支援字串、列表、元組

    in 元素是否存在,支援字串、列表、元組、字典

    not in 元素是否不存在,支援字串、列表、元組、字典

    公共方法:

    len() 計算容器中元素個數

    del() 刪除元素

    max() 返回容器中元素的最大值

    min() 返回容器中元素的最小值

    range(start,end,step) 生成從start到end的數位(其中不包含end數位),步長為step,供for迴圈使用

    enumerate() 將一個可遍歷的資料物件(列表、元組或字串)組合為一個索引序列,同時列出資料和資料下標,一般用在for迴圈中

    enumerate(可遍歷物件, start=0)
    

    容器型別轉換:

    tuple(序列): 將某個序列轉換成元組

    list(序列): 將某個序列轉換成列表

    set(序列): 將某個序列轉換成集合

  33. 推導式(生成式): 列表推導式、字典推導式、集合推導式

    作用: 化簡程式碼

    列表推導式:用一個表示式建立一個有規律的列表或控制一個有規律列表。

    建立0-10的列表:

    list = [i for i in range(10)]
    

    建立0-10的偶數列表:

    list = [i for i in range(10) if i % 2 == 0]
    

    多個for迴圈列表:

    list = [(i , j) for i in range(3) for j in range(3)]
    

    字典推導式:快速合併列表為字典或提取字典中目標資料

    賦值體驗

    dict = {i:i*2 for i in range(1,5)}
    

    將兩個列表合併為字典

    list1 = ['name' , 'age' , 'gender']
    
    list2 = ['Tom' , 20 , 'man']
    
    dict = { list1[i] : list2[i] for i in range(len(list1)) }
    

    提取字典中目標資料

    counts = {'a' : 150 , 'b' : 200 , 'c' : 250}
    
    count = {key : value for key , value in counts.items() if value >= 200}
    

    集合推導式

    list = [1,1,2]
    set = {i * 2 for i in list}
    

三.函數

  1. 函數

    def 函數名(引數):

    「」" 說明檔案內容 「」"

    程式碼1

    程式碼2

    注意:引數可有可無,必須先定義後使用

    函數中return之後的程式碼並不會執行

    help(函數名) 檢視函數解釋說明的資訊

  2. 函數(二)

    區域性變數:只在函數體內部生效的變數

    全域性變數:指在函數體內、外都能生效的變數

    在函數體內部修改全域性變數:在函數體內部用 global 宣告變數為全域性變數後修改

    函數有多個返回值時: return 後面可以直接書寫 元組、列表、字典,返回多個值

    位置引數:呼叫函數時根據函數定義的引數位置來傳遞引數,傳遞和定義引數的順序及個數必須一致

    關鍵字引數:函數呼叫時,通過「鍵=值」的形式加以指定傳參,關鍵字引數之間不存在先後順序

    預設引數:也叫預設引數,用於在定義函數時為引數提供預設值,呼叫函數時可以不傳入有預設值的引數。在定義和呼叫函數時,位置引數必須在預設引數之前

    不定長引數:也叫可變引數,用於不確定呼叫時會傳遞多少個引數的場景,可用 包裹位置引數 或 包裹關鍵字引數 來進行引數傳遞

    包裹位置傳遞(元組):

    def 函數名( *args ): 
        print( args )
    
    函數名( 'abc' , 123 )
    

    包裹關鍵字傳遞(字典):

    def 函數名( **kwargs): 
        print( kwargs )
        
    函數名( a = 'abc' , b = 123)
    

    包裹位置傳遞和包裹關鍵字傳遞都是一個組包的過程,即收集零散資料並組成一個元組或字典

    返回值拆包

    元組: return 10, 20 num1, num2 = 函數 即得到num1 = 10 , num2 = 20

    字典: 對字典拆包,得到的是字典的key

  3. 交換變數值

    方法一:藉助第三變數儲存資料

    方法二: a, b = b, a

  4. 參照: 在python中,值是靠參照來傳遞的

    可以用 id() 來判斷兩個變數是否為同一個值的參照。可以將id理解為那塊記憶體的地址標識。

  5. 可變型別與不可變型別

    可變型別:列表(list)、字典(dict)、集合(set)

    不可變型別:整型、浮點型、字串、元組

  6. 函數加強應用—學員管理系統

    #定義功能介面函數
    def print_info():
        """函數功能介面"""
        print('---select---')
        print('1.add')
        print('2.delete')
        print('3.modify')
        print('4.query')
        print('5.show all')
        print('6.exit')
        print('----end----')
    
    #定義列表等待儲存學員資訊
    info = []
    
    #新增學員資訊函數
    def add_info():
        """學員新增函數"""
        new_name = input('input name:')
        new_id = input('input id:')
        new_tel = input('input telephone:')
    
        global info
    
        for i in info:
            if new_name == i['name']:
                print('name exists!')
                #return 退出當前函數,不執行下面新增資訊的程式碼
                return
    
        info_dict = {}
        info_dict['name'] = new_name
        info_dict['id'] = new_id
        info_dict['tel'] = new_tel
        info.append(info_dict)
        print('add successful!')
    
    #刪除學員資訊
    def del_info():
        """學員刪除函數"""
        del_name = input('input name:')
    
        global info
    
        for i in info:
            if del_name == i['name']:
                info.remove(i)
                print('delete successful!')
                break
        else:
            print('name does not exist!')
    
    #修改學員資訊
    def modify_info():
        """學員資訊修改函數"""
        modify_name = input('input name:')
    
        global info
    
        for i in info:
            if modify_name == i['name']:
                i['tel'] = input('input new telephone:')
                print('modify successful!')
                break
        else:
            print('name does not exist!')
    
    
    #查詢學員資訊
    def search_info():
        """查詢資訊函數"""
        search_name = input('input name:')
    
        global info
    
        for i in info:
            if search_name == i['name']:
                print('---Message---')
                print(f"The name is {i['name']}, The id is {i['id']}, The telephone is {i['tel']}。")
                break
        else:
            print('name does not exist!')
    
    #展示所有學員資訊函數
    def showall_info():
        """展示資訊函數"""
        print('name\tid\ttelephone')
    
        global info
    
        for i in info:
            print(f"{i['name']}\t{i['id']}\t{i['tel']}")
    
    while True:
        #1.顯示功能介面
        print_info()
    
        #2.使用者輸入功能序號
        user_num = int(input('your choice:'))
    
        #3.按照使用者輸入的功能序號,執行不同的功能(函數)
        if user_num == 1:
            add_info()
    
        elif user_num == 2:
            del_info()
    
        elif user_num == 3:
            modify_info()
    
        elif user_num == 4:
            search_info()
    
        elif user_num == 5:
            showall_info()
    
        elif user_num == 6:
            exit_flag = input('are you sure? Y/N')
            if exit_flag == 'Y':
                break
        else:
            print('Error!')
    
  7. 遞迴

    特點: 函數內部自己呼叫自己、必須有出口。

    #遞迴函數求1~n的累加和
    def num(n):
        #出口
        if n == 1:
            return 1
        #函數內部自己呼叫自己
        return n+num(n-1)
    

    若沒有出口,則報錯提示超出最大遞迴深度(996)。

  8. lambda表示式(匿名函數)

    應用場景: 化簡程式碼。如果一個函數只有一個返回值,並且只有一句程式碼,可以使用lambda簡化。

    lambda 參數列: 表示式
    

    lambda表示式的參數列可有可無,函數的引數在lambda表示式中完全適用。

    lambda表示式能夠接收任何數量的引數但只能返回一個表示式的值。

    #計算 a+b 的lambda實現
    fn = lambda a,b: a+b
    print(fn(1,2))
    #輸出結果: 3
    

    lambda的引數形式:無參、有參、預設引數(預設)、可變引數*args、可變引數**kwargs。

    #無參
    fn1 = lambda : 100
    
    #有參
    fn2 = lambda a: a
    
    #預設引數
    fn3 = lambda a,b,c=100: a+b+c
    
    #可變引數 *args(元組)
    fn4 = lambda *args: args
    
    #可變引數 *kwargs(字典)
    fn5 = lambda **kwargs: kwargs
    

    lambda的應用

    #1.帶判斷的lambda
    fn1 = lambda a,b: a if a>b else b  #兩個數比大小
    
    fn2 = lambda n: n+fn2(n-1) if n != 1 else 1  #遞迴求1~n的累加和
    
    
    #2.列表資料按字典key的值排序
    students = [
        {'name':'Tom','age':19},
        {'name':'Alice','age':20},
        {'name':'Hack','age':18}
    ]
    
    students.sort(key=lambda n: n['name'])  #按照名字首字母升序排序
    
    students.sort(key=lambda n: n['age'], reverse=True)  #按照年齡降序排序
    
    
  9. 高階函數

    函數作為引數傳入,這樣的函數稱為高階函數(即複合函數)。

    測試用到的小函數:

    abs():對數位求絕對值

    round():對數位進行四捨五入

    def sum(a, b, f):
        return f(a)+f(b)
    
    result1 = sum(3.14, -2.8, abs)
    result2 = sum(3.14, -2.8, round)
    
    #lambda表示式改寫
    sum = lambda a,b,f: f(a)+f(b)
    

    Python內建高階函數: map()、reduce()、filter()。

    map(func, list) :將傳入的函數變數func作用到列表變數list中的每個元素中,並將結果組成新的列表(python2)/迭代器(python3)返回。

    #計算list1序列中各個數位的三次方
    list1 = [1,2,3,4,5]
    
    def func(x):
        return x ** 3
    
    result = map(func, list1) #此時result為map返回的迭代器
    print(result)  #將返回迭代器result的地址
    print(list(result))  #[1, 8, 27, 64, 125]
    

    reduce(func, list):functools模組中的一個高階函數,其中func必須有兩個引數。每次func結算的結果繼續和序列的下一個元素做累積計算

    #計算list2序列中各個數位的累加和
    import functools  #匯入模組
    
    list2 = [1,2,3,4,5]
    
    def func(a,b):
        return a+b
    
    result = functools.reduce(func,list2)
    
    print(result)  #15
    

    filter(func, list):用於過濾序列,過濾掉不符合條件的元素,並返回一個filter物件。可用 list() 轉換為列表。

    #過濾list3序列中所有的偶數,只留下奇數
    list3 = [1,2,3,4,5,6,7,8,9]
    
    def func(x):
        return x%2 != 0
    
    result = filter(func,list3)
    
    result = list(result)
    print(result)  #[1,3,5,7,9]
    

四.檔案操作

  1. 檔案操作

    作用:把一些內容(資料)儲存存放起來,可以讓程式下一次執行的時候直接使用,而不必重新制作一份,省時省力。

    檔案操作步驟:開啟檔案、讀寫等操作、關閉檔案。

    open():開啟一個已經存在的檔案,或建立一個新檔案。

    f = open(name, mode)
    
    #name: 是要開啟的目標檔名的字串(可以包含檔案所在的具體路徑)
    #mode: 設定開啟檔案的模式(存取模式):唯讀、寫入、追加等
    #此時f為name檔案的檔案物件,可通過f執行之後的讀寫等操作
    
    主存取模式描述
    r以唯讀方式開啟檔案。檔案的指標將會放在檔案的開頭。這是預設模式(存取模式未指定時,即為唯讀模式)。
    w開啟一個檔案只用於寫入。如果該檔案已存在則開啟檔案,並從開頭開始編輯,即原有內容會被刪除。如果該檔案不存在,建立新檔案。
    a開啟一個檔案用於追加。如果該檔案已存在,檔案指標將會放在檔案的結尾。也就是說,新的內容將會被寫入到已有內容之後。如果該檔案不存在,建立新檔案進行寫入。
    (b)以二進位制形式讀取
    (+)可讀可寫

    存取模式r+、w+、a+的區別

    r+ :沒有該檔案則報錯,檔案指標在開頭故能讀取資料

    w+ :沒有該檔案會新建,檔案指標在開頭並會用新內容覆蓋原有內容,故無法讀取檔案內原有的資料

    a+ :沒有該檔案會新建,檔案指標在結尾故不能讀取資料

    寫入內容:write()

    檔案物件.write('內容')
    

    讀取內容:read()、readlines()、readline()。

    檔案物件.read(num)
    #num 表示要從檔案中讀取的資料的長度。不寫則預設讀取所有資料。其中換行符'\n'會佔一位
    
    檔案物件.readnlines()
    #按照行的方式把整個檔案的內容進行一次性讀取,並返回一個列表,其中每一行資料為一個元素
    
    檔案物件.readline()
    #一次讀取一行內容、重複呼叫readline()則依次讀取檔案中每一行的內容
    

    移動檔案指標:seek()

    檔案物件.seek(偏移量,起始位置)
    
    #起始位置引數: 0開頭 1當前 2結尾
    

    應用:

    #使用 a 存取模式開啟檔案,通過改變檔案指標位置來讀取資料
    f = open('test.txt','a')
    
    f.seek(0,0)  #此時可簡寫為 f.seek(0)
    con = f.read()
    
    f.close()
    
  2. 檔案備份案例

    #使用者輸入當前目錄下任意檔名,程式完成對該檔案的備份功功能(備份檔名為 xx[備份].字尾)
    
    #1.接收使用者輸入的檔名
    old_name = input('input yoru backup file name:')
    
    #2.規劃備份檔名
    index = old_name.rfind('.')  #檔名中'.'的位置
    if index > 0:  #判斷檔名,防止出現'.txt'類的無效檔名
        postfix = old_name[index:]
    
    new_name = old_name[:index] + '[備份]' + postfix  #利用字串的切片重新規劃備份檔名
    
    #3.備份檔案寫入資料
    old_f = open(old_name,'rb')
    new_f = open(new_name,'wb')
    
    while True:  #迴圈讀取,防止檔案過大時卡死
        con = old_f.read(1024)
        if len(con) == 0:  #讀取完成時
            break
        new_f.write(con)
    
    new_f.close()
    old_f.close()
    
  3. 檔案和資料夾的操作

    模組:使用 os 模組

    import os
    
    #1.檔案操作
    #檔案重新命名,也可以重新命名資料夾
    os.rename(目標檔名或路徑, 新檔名)
    
    #檔案刪除,也可以刪除資料夾
    os.remove(目標檔名)
    
    #2.資料夾操作
    #建立資料夾
    os.mkdir(資料夾名字)
    
    #刪除資料夾
    os.rmdir(資料夾名字)
    
    #3.目錄操作
    #獲取當前目錄
    os.getcwd()
    
    #改變當前預設目錄
    os.chdir(目錄資料夾)
    
    #獲取目錄列表
    os.listdir(目錄資料夾)
    
  4. 檔案和資料夾操作應用案例

     #批次修改檔名,既可新增指定字串,又能刪除指定字串
    
    import os
    
    #構造條件資料
    flag = input('輸入操作型別(1為新增,2為刪除):')
    
    #構造指定字串
    str = input('請輸入指定字串:')
    
    #找到所有檔案
    file_list = os.listdir()
    
    #新增或刪除指定字串
    for i in file_list:
        if flag == '1':
            new_name = str + i
        elif flag == '2':
            num = len(str)
            new_name = i[num:]
        else:
            print('操作模式輸入錯誤!')
            break
        #重新命名
        os.rename(i, new_name)
    

五.物件導向

  1. 是對一系列具有相同特徵和行為的事物的統稱,是一個抽象的概念,不是真實存在的事物。物件是由類建立出來的真實存在的事物。

    #建立類
    class 類名():  #類名要滿足識別符號命名規則,同時遵循大駝峰命名習慣
        程式碼
        ......
    	def 函數名(self):  #self指呼叫該函數的物件
            程式碼
    
    #建立物件
    物件名 = 類名()
    
  2. 類外面新增物件屬性

    物件名.屬性名 =

    類外面獲取物件屬性

    物件名.屬性名
    

    類裡面獲取物件屬性

    self.屬性名
    

    綜合範例

    class Washer():
        def wash(self):
            print('wash the clothes!')
        def get_size(self):
            print(f'此洗衣機的尺寸是{self.width} X {self.height}')
    
    haier1 = Washer()
    haier1.width = 500
    haier1.height = 300
    
    haier2 = Washer()
    haier2.width = 600
    haier2.height = 400
    
    print(haier1.width)
    haier1.get_size()
    haier2.get_size()
    
  3. 魔法方法: __init__() 、 __str__()、__del__()。

    #1. __init__() 初始化物件。
    #建立物件時預設被呼叫;不需開發者傳遞self引數,python直譯器會自動把當前物件參照傳遞過去。
    
    class washer():
        def __init__(self,width,height):
            self.width = width
            self.height = height
    
        def print_info(self):
            print(f'{self.width} X {self.height}')
    
    h = washer(500,800)
    h.print_info()
    #輸出結果 500 X 800
    
    #2. __str__() 使得用print輸出物件時,輸出該方法中return的資料,而不再輸出物件的記憶體地址。
    
        def __str__(self):
            return "這是洗衣機物件!"
        
    print(h)
    #輸出結果 這是洗衣機物件!
    
    #3. __del__() 當刪除物件時,python直譯器會預設呼叫__del__()方法
    
        def __del__(self):
            print(f'{self}物件已經被刪除!')
         
    del h
    #輸出結果 <__main__.washer object at 0x000002531DF744F0>物件已經被刪除!
    
  4. 兩個案例

    烤地瓜

    #需求:1.被烤時間和地瓜狀態相對應  2.使用者可按意願新增調料
    
    class SweetPotato():
    
        def __init__(self):
            self.cook_time=0
            self.cook_state='生的'
            self.condiments=[]
    
        def cook(self, time):
            if time >=0:
                self.cook_time += time
                if 0<= self.cook_time < 3:
                    self.cook_state = '生的'
                elif 3 <= self.cook_time < 5:
                    self.cook_state = '半生不熟'
                elif 5 <= self.cook_time < 8:
                    self.cook_state = '熟了'
                elif self.cook_time >= 8:
                    self.cook_state = '糊了!'
            else:
                print('時間刺客?!')
    
        def add_condiment(self, con):
            self.condiments.append(con)
    
        def __str__(self):
            return f'這個地瓜烤了{self.cook_time}分鐘,狀態是{self.cook_state},新增的調料有{self.condiments}'
    
    p = SweetPotato()
    p.add_condiment('番茄醬')
    print(p)
    p.cook(8)
    p.add_condiment('芥末')
    print(p)
    
    # 這個地瓜烤了0分鐘,狀態是生的,新增的調料有['番茄醬']
    # 這個地瓜烤了8分鐘,狀態是糊了!,新增的調料有['番茄醬', '芥末']
    

    搬傢俱

    #需求 將小於房子剩餘面積的傢俱擺放到房子中
    
    class Furniture():
        def __init__(self,name,area):
            self.name = name
            self.area = area
    
    class House():
        def __init__(self,adress,area):
            self.adress = adress
            self.area = area
            self.free_area = area
            self.furniture = []
    
        def add_furniture(self,item):
            if self.free_area >= item.area:
                self.furniture.append(item.name)
                self.free_area -= item.area
            else:
                print('傢俱太大,剩餘面積不足,無法容納')
    
        def __str__(self):
            return f'這個房子的地址是{self.adress},總面積是{self.area},當前剩餘面積是{self.free_area},傢俱有{self.furniture}'
    
    bed = Furniture('雙人床',6)
    sofa = Furniture('沙發',10)
    court = Furniture('高爾夫球場',1000)
    house = House('陸家嘴',200)
    print(house)
    house.add_furniture(bed)
    house.add_furniture(sofa)
    house.add_furniture(court)
    print(house)
    
    #這個房子的地址是陸家嘴,總面積是200,當前剩餘面積是200,傢俱有[]
    #傢俱太大,剩餘面積不足,無法容納
    #這個房子的地址是陸家嘴,總面積是200,當前剩餘面積是184,傢俱有['雙人床', '沙發']
    
  5. 繼承: Python物件導向的繼承指的是多個類之間的所屬關係,即子類預設繼承父類別的所有屬性和方法,具體如下:

    #定義父類別A
    class A(object):
        def __init__(self):
            self.num = 1
            
        def infor_print(self):
            print(self.num)
            
    #定義子類B,繼承父類別A
    class B(A):
        pass
    
    #建立物件,驗證物件繼承
    result = B()
    result.info_print()
    

    在python中,所有類預設繼承object類,object類是頂級類或基礎類別;其他子類叫派生類

    拓展:python2中的經典類 和 python3中的新式類

    #經典類(不由任意內建型別派生出的類)
    class 類名:
        程式碼
        ......
        
    #新式類
    class 類名(object):
        程式碼
        ......
        
    #在今後的學習和運用中,統一使用新式類
    

    單繼承:一個子類繼承一個父類別,這種單一的繼承關係稱為單繼承。

    多繼承:一個子類同時繼承多個父類別。

    class 子類(父類別A,父類別B,父類別C)
    #當兩個父類別中的屬性和方法有同名時,優先繼承第一個父類別中的同名屬性和方法,即繼承A類。
    

    子類重寫父類別同名屬性與方法:在子類中可以重寫與父類別中同名的屬性和方法。子類建立的物件呼叫屬性和方法時,會呼叫子類中重寫的屬性和方法。

    拓展: **__mro__**順序 方法檢視類的繼承層級順序。

    print(類名.__mro__)
    

    子類呼叫父類別同名屬性和方法:在子類中重寫了父類別中同名屬性與方法的情況下,呼叫父類別中的同名屬性和方法。

    class 子類B(父類別A):
        def 同名方法(self):
            #如果之前呼叫了父類別的屬性和方法,則父類別屬性會覆蓋子類屬性,故在呼叫子類屬性前,先呼叫子類自己的初始化
            self.__init__(self)
            程式碼
            
        def 呼叫父類別方法(self):
            #呼叫父類別方法,為保證呼叫到的屬性也是父類別的屬性,必須在呼叫方法前呼叫父類別的初始化
            父類別A.__init__(self)
    		父類別A.同名方法(self)
    

    多層繼承:一般指大於兩層的繼承關係。

    class A(object):
    	...
        
    class B(A):
        ...
        
    class C(B):  #多層繼承
        ...
    

    super()呼叫父類別方法:自動查詢父類別,直接呼叫父類別的屬性方法,呼叫順序遵循__mro__類屬性的順序。

    class A(object)
    class B(A)
    
    class C(B):
        #方法一:原始方法
        def useAB(self):
            A.__init__(self)
            A.同名方法(self)
            B.__init__(self)
            b.同名方法(self)
            
        #方法二:super()方法
        #方法2.1 super(當前類名,self).函數()
        def useAB(self):
            super(C,self).__init__()
            super(C,self).同名方法() 
            #此時會呼叫父類別B的方法;若想呼叫A類的方法,需要在B類的同名方法中新增同樣的super方法程式碼來呼叫A類
            
        #方法2.2 super().函數()
        def useAB(self):
            super().__init__(self)
            super().同名方法()
            #同樣呼叫父類別B的方法;無法直接呼叫父類別的父類別A的屬性和方法
    
  6. 私有許可權

    **設定私有屬性和方法:在屬性名和方法名 **前面加上兩個下劃線。

    私有屬性和私有方法只能在類記憶體取和修改,即子類無法繼承或直接存取父類別的私有屬性和方法。

    class A(object):
        def __init__(self):
            self.name = 'A'
            self.__money = 99999  #私有屬性
        
        def __CostMoney(self,money):  #私有方法
            self.__money -= money
    

    獲取和修改私有屬性值:可在類內定義公有函數來獲取和修改 私有屬性值,在類外呼叫該函數來實現獲取和修改私有屬性功能。

    #一般在類內用函數名get_xx來獲取私有屬性,用set_xx來修改私有屬性
    class A(object):
        def __init__(self):
            self.__money = 99999
            
        def get_money(self):
            return self.__money
        
        def set_money(self,new_money):
            self.__money = new_money
            
    class B(A):
        pass
    
    b = B()
    
    b.get_money()  #成功獲取父類別中的私有屬性
    b.set_money(0)  #成功修改父類別中的私有屬性
    
  7. 多型:一種使用物件的方式,子類重寫父類別方法,呼叫不同子類物件的相同父類別方法,可以產生不同的執行結果。即傳入不同的物件,產生不同的結果。

  8. 類屬性和範例屬性:類屬性即類所擁有的屬性,它為該類所有物件共有。類屬性可以用 類物件範例物件 存取。

    類屬性只能通過類物件修改

    #修改類屬性
    類名.屬性 =
  9. 類方法:需要用裝飾器 @classmethod 來標識其為類方法,類方法第一個引數必須是類物件,一般以 cls 作為第一個引數。

    class A(object):
        __num = 777
        
        @classmethod
        def get_num(cls):
            return cls.__num
        
    obj = A()
    print(obj.get_num())
    
  10. 靜態方法:通過裝飾器 @staticmethod 進行修飾,靜態方法即不需要傳遞類和物件的方法,有利於減少不必要的記憶體佔用和效能消耗。

    class A(object):
        @staticmethod
        def info_print():
            print('這是A類')
    

六.異常

  1. 異常的定義:直譯器檢測到錯誤時無法繼續執行,並出現一些錯誤的提示,這就是所謂的異常

    異常的作用:使得直譯器檢測到錯誤時,轉而執行另一句沒錯誤的語句,使得程式不因一個錯誤而停止下來。

  2. 基本寫法

    try:
        可能發生錯誤的程式碼
    except:
        出現異常時執行的程式碼
    else:
        沒有異常時執行的程式碼
    finally:
    	無論是否異常都要執行的程式碼
    

    體驗案例:

    #需求:嘗試以r模式開啟檔案,若檔案不存在(發生錯誤),則以w方式開啟
    try:
        f = open('test.txt','r')
    except:
        f = open('test.txt','w')
    
  3. 捕獲指定異常

    try:
        print(num)
    except (NameError, ZeroDivisionError) as result:
        print(result)  #捕獲的異常描述資訊
        num = 777
        print(num)
       
    #若嘗試執行程式碼的異常型別和要捕獲的異常型別不一致,則無法捕獲異常
    #一般try下方只放一行嘗試執行的程式碼
    
  4. 捕獲所有異常:利用 Exception 類

    #Exception是所有程式異常類的父類別
    try:
        可能錯誤的程式碼
    except Exception as result:
        print(result)
    
  5. 異常中的 else 和 finally:

    try:
        f = open('test.txt','r')
    except Exception as result:
        f = open('test.txt','w')
        print(result)
    else:  # try 下方的程式碼無異常時執行的程式碼
        print('程式碼沒有異常和錯誤')
    finally:  #無論有無異常都要執行的程式碼,如關閉檔案
        f.close()
    
  6. 異常的傳遞

    import time
    try:
        f = open('test.txt') #預設開啟模式為唯讀
        #嘗試迴圈讀取內容
        try:
            while True:
                con = f.readline()
                #無內容時退出迴圈
                if len(con) == 0:
                    break
                time.sleep(2)
                print(con)
        except:
            #在命令提示字元中按下 Ctrl+C 終止程式
            print('程式被意外終止')
    except:
        print('檔案不存在')
    
  7. 自定義異常: 丟擲自定義異常的語法為raise 異常類物件

    #自定義異常類,繼承Exception
    class ShortInputError(Exception):
        def __init__(self,length,min_length):
            self.length=length
            self.min_length=min_length
    
        #設定丟擲異常的描述資訊
        def __str__(self):
            return f'輸入長度為{self.length},不能少於{self.min_length}個字元'
    
    def main():  #封裝程式碼
        try:
            con = input('請輸入密碼: ')
            if len(con) < 6:
                raise ShortInputError(len(con),6)
        except Exception as result:
            print(result)
        else:
            print('密碼輸入完成')
            
    main()
    

七.模組

  1. 瞭解模組:Python模組(Module),是一個Python檔案,包含了Python物件定義和語句。

  2. 匯入和呼叫模組

    #匯入及呼叫模組
    
    #寫法一
    import 模組名  #匯入模組中的所有程式碼
    模組名.功能名()
    
    #寫法二
    from 模組名 import 功能1,功能2...  #單個呼叫某功能
    功能名()   #即不需要在功能前寫 "模組名."
    
    #寫法三
    from 模組名 import *
    功能名()  
    
    #一般用第一種寫法
    

    利用as定義別名:定義別名後,使用時要用定義的別名

    #模組定義別名
    import 模組名 as 別名
    
    #功能定義別名
    from 模組名 import 功能 as 別名
    
  3. 製作模組:模組名字就是py檔案的名字。自定義模組名必須要符合識別符號命名規則

    #只會在當前檔案中呼叫下列測試程式碼,其他匯入的檔案內不符合該條件,也就不會執行測試程式碼
    # __name__ 是系統變數,是模組的識別符號。如果在自身模組裡,則其值為 '__main__';否則是所在模組的名字
    if __name__ == '__main__':
        測試模組功能程式碼
    
  4. 模組定位順序:當匯入一個模組,Python直譯器對模組位置的搜尋順序是:

    當前目錄 > 搜尋在shell變數PYTHONPATH下的每個目錄 > 作業系統的預設python路徑

    注意

    自己的檔名不要和已有模組名重複,否則模組功能無法使用。

    使用from 模組名 import 功能時,若功能名字重複,則呼叫最後定義的或最後匯入的功能。

    當使用 import 模組名 的寫法呼叫模組時,不需要擔心功能名重複。

  5. __all__列表:如果一個模組檔案中有__all__ 變數列表,當使用from 模組名 import *匯入該模組時,則只能匯入__all__列表中的元素。

  6. :包將有聯絡的模組組織在一起,放到同一個資料夾下,並且在這個資料夾內自動生成一個名字為__init__.py的檔案,這個檔案控制著包的匯入行為。

    建立包:在Pycharm中 New -> Python Package -> 輸入包名 - > [OK] 即可新建一個包。

    匯入包

    #方法一
    import 包名.模組名
    包名.模組名.功能
    
    #方法二
    #注意,必須在 __init__.py 檔案中新增 __all__ = [] 來控制允許匯入的模組列表
    from 包名 import *
    模組名.功能
    

八.物件導向綜合範例

#使用物件導向程式設計思想完成學員管理系統的開發

#為了方便維護程式碼,一般一個角色一個程式檔案
#專案要有主程式入口,習慣為main.py

#系統要求:學員資料儲存在檔案中
#系統功能:新增學員、刪除學員、修改學員資訊、查詢學員資訊、顯示所有學員資訊、儲存學員資訊、退出系統等功能


#student.py
#學員類
class Student(object):
    def __init__(self,name,gender,tel):
        #姓名、性別、手機號
        self.name = name
        self.gender = gender
        self.tel = tel

    def __str__(self):
        return f'{self.name},{self.gender},{self.tel}'


#mangerSystem.py
#儲存資料的: student.data
#儲存資料的形式: 列表儲存學員物件
#系統功能: 新增、刪除、修改、查詢、顯示、儲存學員資訊

#管理系統類
class StudentManager(object):
    def __init__(self):
        #儲存資料所用列表
        self.student_list = []

    #一. 程式入口函數,啟動程式後執行的函數
    def run(self):
        #1. 載入學員資訊
        self.load_student()

        while True:
            #2. 顯示功能選單
            self.show_menu()
            #3. 使用者輸入目標功能序號
            menu_num = int(input('請輸入您需要的功能序號: '))

            #4. 根據使用者輸入的序號執行相應功能
            if menu_num == 1:
                # 新增學員
                self.add_student()

            elif menu_num == 2:
                # 刪除學員
                self.del_student()

            elif menu_num == 3:
                # 修改學員資訊
                self.modify_student()

            elif menu_num == 4:
                # 查詢學員資訊
                self.search_student()

            elif menu_num == 5:
                # 顯示所有學員資訊
                self.show_menu()

            elif menu_num == 6:
                # 儲存學員資訊
                self.save_student()

            elif menu_num == 7:
                # 退出系統 - 退出迴圈
                break

    #二. 系統功能函數
    #2.1 顯示功能選單 -- 靜態方法
    @staticmethod
    def show_menu():
        print('請選擇如下功能: ')
        print('1.新增學員')
        print('2.刪除學員')
        print('3.修改學員資訊')
        print('4.查詢學員資訊')
        print('5.顯示所有學員資訊')
        print('6.儲存學員資訊')
        print('7.退出系統')

    #2.2 新增學員
    def add_student(self):
        #1. 使用者輸入
        name = input('請輸入姓名: ')
        gender = input('請輸入性別: ')
        tel = input('請輸入手機號: ')

        #2. 建立學員物件 -- 先匯入student.py模組
        student = Student(name,gender,tel)

        #3. 將物件新增到學員列表
        self.student_list.append(student)

    #2.3 刪除學員
    def del_student(self):
        #1. 使用者輸入目標學員姓名
        del_name = input('請輸入要刪除的學員姓名:')

        #2. 如果使用者輸入的目標學員存在則刪除,否則提示不存在
        for i in self.student_list:
            if i.name == del_name:
                self.student_list.remove(i)
                break
        else:
            print('查無此人!')

    #2.4 修改學員資訊
    def modify_student(self):
        #1. 使用者輸入目標學員姓名
        modify_name = input('請輸入要修改的學員姓名: ')

        #2. 如果使用者輸入的目標學員存在,則修改資訊,否則提示不存在
        for i in self.student_list:
            if i.name == modify_name:
                i.name = input('請輸入學員姓名: ')
                i.gender = input('請輸入學員性別: ')
                i.tel = input('請輸入學員手機號: ')
                print('修改成功!')
                break
        else:
            print('查無此人!')

    #2.5 查詢學員資訊
    def search_student(self):
        #1. 使用者輸入目標學員姓名
        search_name = input('請輸入要查詢的學員姓名: ')

        #2. 若存在,列印學員資訊,否則提示不存在
        for i in self.student_list:
            if i.name == search_name:
                print(f'姓名{i.name},性別{i.gender},手機號{i.tel}')
                break
        else:
            print('查無此人!')

    #2.6 顯示所有學員資訊
    def show_student(self):
        print('姓名\t性別\t手機號')
        for i in self.student_list:
            print(f'{i.name}\t{i.gender}\t{i.tel}')

    #2.7 儲存學員資訊
    def save_student(self):
        # 拓展 __dict__方法,以字典方式返回類和物件內的屬性
        #1. 開啟檔案
        f = open('student.data','w')

        #2. 檔案寫入學員資料 - 先將學員物件資料轉換成列表字典資料再做儲存
        new_list = [i.__dict__ for i in self.student_list]
        # 檔案內資料要求為字串型別,故要先轉換資料型別為字串才能寫入檔案
        f.write(str(new_list))

        #3. 關閉檔案
        f.close()

    #2.8 載入學員資訊
    def load_student(self):
        #嘗試以"r"模式開啟資料檔案,有異常則用"w"模式開啟;存在則讀取資料
        try:
            f = open('student.data','r')
        except:
            f = open('student.data','w')
        else:
            #1. 讀取資料
            data = f.read()

            #2. 先將檔案中的 字串型字典資料 轉換為 物件資料 後再儲存到學員列表
            new_list = eval(data)
            self.student_list = [Student(i['name'],i['gender'],i['tel']) for i in new_list]

        finally:
            #3. 關閉檔案
            f.close()

#main.py

#匯入模組
#from managerSystem import *

#啟動管理系統
#if __name__ == '__main__':
student_manager = StudentManager()
student_manager.run()