python介面自動化測試之python基礎語法

duncan1863發表於2020-08-30

一、pycharm的使用和python基本語法

(一)、pycharm的使用和python環境

1、python以及pycharm的安裝

  • python 的版本選擇:3.x 版本,不要安裝2.x 版本,有很多語法不一樣
  • 如何確定自己 python 版本: cmd: python
    • 不是內部命令:python沒有正確安裝,原因大概率是因為沒有配置環境變數(配置環境變數後重啟電腦生效)
    • 指定 python 的安裝目錄:一般來說是安裝在 d:\python37
  • 測試python是否安裝成功
    • cmd: python
    • cmd: pip ,或者 pip3 , 有任何一個出現命令不存在,
    • 額外注意:loadrunner 中也有pip,這個pip配置環境變數了之後,python中的pip也需要配置環境變數
  • prcharm 的版本選擇:社群版夠用
  • pycharm 只是一個工具,python 才是關鍵

2、pycharm 新建專案

  • 新建專案
    • file ---> New Project
  • 退出專案
    • file ---> Close Project
  • 切換專案
    • file ---> Open
    • file ---> Open Recent

3、檔案、目錄、包的建立和管理

  • Project ---> 右鍵 ,可以新建檔案、目錄和包

4、pycharm 的基礎使用

  • python 程式碼是儲存到以 .py 結尾的檔案當中
  • .py 檔案又是放到各個資料夾(目錄)下面的

5、如何執行程式碼:

  • 右鍵,點選 run
  • 命令列執行:點選底下的 Terminal
    • 進入專案路徑
    • python 拼接好的路徑/python檔案.py

6、安裝第三方庫

  • 第三方庫:是別人已經寫好的 python 程式碼

  • 第一種方法:

    • 安裝:pip install 庫名
    • 解除安裝:pip uninstall 庫名
  • 第二種方法:pycharm :不要勾選 user's site package

  • 第三種方法:庫放在國外的伺服器上,需要用到國內安裝源,python國內源

python國內源:
清華:https://pypi.tuna.tsinghua.edu.cn/simple
阿里雲:http://mirrors.aliyun.com/pypi/simple/
中國科技大學 https://pypi.mirrors.ustc.edu.cn/simple/
華中理工大學:http://pypi.hustunique.com/
山東理工大學:http://pypi.sdutlinux.org/
豆瓣:http://pypi.douban.com/simple/

(二)、python基本語法

1、基本語法

  • print 輸出

    • 表示在螢幕上列印出(顯示出)
    • 使用的任何的程式碼,雙引號是半形,英文
    • print 預設輸出是換行的,不同的資料之間用逗號隔開
  • python註釋: 表示在 python 當中不會執行的文字(不會當成程式碼), 是說明下面的程式碼是什麼?

    • # 表示單行註釋 , Ctrl + /
    • """ """ 表示多行註釋
    • ''' ''' 表示多行註釋
  • 縮排:

    • 現在這個階段,所有的程式碼全部頂格寫,不要進行縮排。
  • 數值

    • 和數學中的數值表示是一樣的(注意點:數值不用加引號)
  • 字串

    • python 使用引號來表示字串(一串文字)
  • 變數

    • 什麼是變數:是用來儲存資料
      • a = 100
      • b = 200
      • c = “ hello world”
    • 變數名的命名規範:
      • 只能包含數字、字母、下劃線,
      • 不能以數字開頭,
      • 不能有關鍵字( 注意點 )
        • python 中所有的關鍵字: keyword.kwlist
      • 儘量做到見名知意
        • 儘量不要用拼音
  • 識別符號:(凡是我們自己取的名字,都是識別符號。)

    • 規範:識別符號由字母、數字、下劃線組成,不能使用關鍵字
    • 識別符號包括:變數名、函式名、類名、模組名、專案名
    • 在python中,所有識別符號可以包括英文,數字以及下劃線(_),但不能以數字開頭。
    • python 中的識別符號是區分大小寫的,大寫的 A 和小寫的 a 不一樣
  • 識別符號的命名風格:

    • 下劃線命名法:
      • 規範:單詞字母小寫,單詞之間使用下劃線連線
      • 如:max_number ,test_data
    • 大駝峰命名法:
      • 規範:每個單詞的第一個字母大寫
      • 如:MaxNumber , TestData
    • 小駝峰命名法:
      • 規範:第一個單詞以小寫字母開始,第二個單詞的首字母大寫
      • 如:maxNumber , testData

  • input 使用者輸入

    • 從控制檯裡面獲取一個資料,獲取到的型別是字串型別

二、python中常見資料型別

(一)、數值型別 & 運算子

1、數值型別資料

  • 數值型別
    • 整數(int):整數
    • 浮點數(float):小數
    • 布林值(bool):只有兩個值 True 和 False

2、python 常見運算子

  • 算術運算子:

    • +
    • -
    • *
    • /
      • 除法運算一定要注意:除數不能為0
      • 除數如果為0,就會報錯:ZeroDivisionError: division by zero
    • //
      • 整除
    • %
      • 餘數:模運算

    # +
    print(5 + 6)
    # -
    print(7 - 8)
    # *
    print(2 * 3)
    # /
    # 只要是進行除法運算,得到的是一個 float
    print(4 / 3)
    print(4 / 2)
    
    # 除法運算一定要注意,除數不能為 0
    # 除數如果為0,就會報錯:ZeroDivisionError: division by zero
    # 程式報錯以後,就無法繼續執行
    # print(2/0)
    # print('hello world')
    
    # // 得到的是一個整數。  整除
    print(4 // 3)
    
    # %  取餘數 : 模運算
    print(4 % 3)
    
    # ** 冪運算 4的3次方
    print(4 ** 3)
    
  • 賦值運算子

    • =
    • +=
    • -=
    • *=
    • /=
    • //=
    • %=
    • **=
    name = 'yuze'
    age = 18
    
    #漲一歲
    age = age + 1
    print(age)
    
    #縮寫 age += 1    ==>   age = age + 1
    age += 2
    print(age)
    
    age /= 3
    print(age)
    

  • 比較運算子: 比較運算得到的結果是一個 bool 值, True 或 False

    • <
    • >
    • <=
    • >=
    • !=
    > 大於
    print(5 > 4) # True
    
    < 小於
    print(6 < 3) # False
    
    >= 大於等於
    print(6 >= 3) # True
    
    <= 小於等於
    print(6 <= 3) # False
    
    != 不等於
    print(6 != 3) # True
    
    TODO: == 才是比較運算, 一個 = 是賦值運算
    print(6 == 6)
    

  • 邏輯運算 : 可以使用()提高優先順序

    • and
    • or
    • not
    a = 3 > 4
    print(a)
    
    b = 4 != 5
    print(b)
    
    # 運算 and
    # 每一個都為 True
    
    print(a and b)  # False
    
    # 運算 or
    # 只要有一個為 True
    
    print(a or b)  # True
    
    # 練習
    
    a = True
    b = 5 == 4  # False
    c = 5 != 3  # True
    
    print(a and b or c)  # True
    print(a or b and c)  # True
    
    # python 的運算有沒有優先順序,如何設定優先順序
    # 使用 () 設定優先順序
    print(((a and b) or c) and b)
    
    # not 取反
    print(not(b))  # True
    
  • 身份運算

    • is
    • is not
  • 成員運算

    • in
    • not in
    # in
    
    name = 'yuz'
    
    print('u' in name)  # True
    print('uz' in name)  # True
    print('uai' in name)  # False
    
    # TODO: in 一定是連著的, yz 是一個整體
    print('yz' in name)  # False
    print('Y' in name)  # False
    

3、隨機數模組: random (python 官方庫)

  • 隨機生成 0-1 之間的浮點數:random.random()

  • 隨機生成 0-100 之間的浮點數:random.randint(1, 100)

    import random
    f_num = random.random()
    
    print(f_num)
    
    num = random.randint(0, 100)
    
    print(num)
    

(二)、字串

本節問題:

問題一:python中如何表示字母,比如要將一個人的名字儲存下來?

問題二:字串如何定義?

問題三:字串如果要換行怎麼辦?

問題四:數值型別的資料可以轉換成字串嗎?

問題五:可以把兩個字串組成一個嗎?

問題六;如何獲取字串中某個具體的字元?

1、字串的定義:

  • 單引號、雙引號:定義單行字串

  • 三引號、三雙引號: 多行字串定義

  • 空字串: s=''

  • str():

  • 注意點:字串中有單引號時,外面用雙引號注意區分

    """字串的定義
    
    如何表示字串:
    - 引號表示字串
    - 單引號 ''
    - 雙引號 ""
    - 三引號 ''' '''
    - 三雙引號 """ """
    """
    
    name1 = "yuze"
    
    print(name1)
    
    name2 = 'yuze'
    
    print(name2)
    
    name3 = '''yuze'''
    
    print(name3)
    
    name4 = """yuze"""
    
    print(name4)
    
    print(name1 == name2 == name3 == name4)  # True
    
    print(name1 == name2)  # True
    
    print(name1 == name3)  # True
    
    print(name1 == name4)  # True
    

2、字串的切片和下標取值

  • 1、下標索引取值

    • 下標取值:可以正向取,也可以反向取
    • 注意點:正向從 0 開始,反向從 -1 開始
    name = 'yuzwang'
    
    print(name[1]) # u
    
    print(name[0]) # y
    
    # 獲取第3個字元
    
    print(name[2])  # z
    
    # 獲取 g
    
    print(name[6])
    
    print(name[-1])
    

  • 2、切片: [:][::]

    • 問題:下標取值只能獲取單個元素,現有字串 str1='hello python' ,如果要獲取出來 python 應該怎麼做?
    • 切片的語法: 和下標取值一樣使用中括號進行切片,有兩種用法:
      • [a:b] :a代表起始位置下標, b 代表終止位置下標(左閉右開);
      • [a: b: c] : a代表起始位置下標, b 代表終止位置下標(左閉右開),c 代表步長。
    
    """字串的切片 slice
    
      獲取多個字元
    
      索引獲取的公式:
    
          m_str[start:end:step]
    
      注意:end - start 的符號 必須和 step 的符號相同才可以獲取到索引
    
      step 的值不能為0
    
    """
    
    name = 'yuzwang'
    
    # 要 1 和 2
    print(name[1:2]) # u
    print(name[0:1]) # y
    
    # TODO: 這個才是對的
    # TODO: 顧頭不顧腚,取頭不取尾,取左不取右
    print(name[0:2]) # yu
    print(name[3:6])  # wan
    
    # 什麼是 step , 取完第一個索引,把索引 + 多少
    # step = 2
    print(name[3:6:2]) # wn
    print(name[1:5:3]) # ua
    
    # step 可以為負數
    print(name[5:1:-3]) # nz
    print(name[5:1:3])  # 取不到值 None
    print(name[1:4:-2])  # 取不到值 None
    
    # TODO: end - start 的符號 必須和 step 的符號相同才可以獲取到索引
    # TODO:step 的值不能為0,否則會報錯:ValueError: slice step cannot be zero
    print(name[1:5:0])
    
    # TODO: IndexError
    print(name[1000000]) # IndexError: string index out of range
    print(name[1:1000000])  # uzwang 不會報錯,會取到所有值
    
    name = "yuzewang"
    
    # 省略 end ,表示取到最後
    print(name[1:])
    
    # 省略 start ,表示從 0 開始
    print(name[:5])
    
    # 複製,copy  從頭到尾,
    # TODO: 面試題:複製字串
    print(name[:])
    name_copy = name[:]
    print(name_copy)
    
    # 倒序  '123456' ==> '654321'
    # TODO:面試題:倒序一個字串
    print(name[::-1]) # gnawezuy
    

3、字串拼接和轉義

  • + 號:'hello' + 'python'

  • 字串轉義:

    • \n: 換行符
    • \t: 水平製表符
    • 關閉轉義:r'hello \n python'
    
    name = 'yuz'
    family_name = 'wang'
    
    print(name + family_name)
    
    print(name + ' ' + family_name)
    
    字串和數字能不能相加
    
    print('yuz' + 7) # 字串和數字不能直接相加,會報錯:TypeError: must be str, not int
    
    print('yuz' + str(7))  # yuz7
    
    資料型別的轉化
    
    print(int(name))  # 報錯:ValueError: invalid literal for int() with base 10: 'yuz'
    
    print(int('12')) # 12
    
    print(bool(34)) # True
    
    bool 轉化,只要是非0,非空的就是True
    
    字串換行
    
    '\' 不會分開成兩行
    
    name = "yuze ooasfjojo" \
    
                 "wefwllfjlj"
    
    print(name)  # yuze ooasfjojowefwllfjlj
    
    # 三引號換行,得到多行資料
    
    name = """yuze flaljlkfjlajl
    
    lsajllakj fjk
    
    sjljjfljladf
    
    aljfl
    
    """
    
    print(name)
    
    # 單引號中 \n 表示換行
    
    name = 'kaixina lajj\nlfljajljssfjdlk\njljajs'
    
    print(name)
    
    

4、字串常用方法

  • join : 字串拼接

name = "qin er cai"

# 字串拼接

print(name + 'wang')

# 使用 join 拼接

print(name.join(['a','b','c']))  # aqin er caibqin er caic

# 時間 ['2020', '08', '03'] 用 / 連線起來

print('/'.join(['2020', '08', '03'])) # 2020/08/03

print('2020' + '/' + '08' + '/' + '03') # 2020/08/03


  • find : 查詢元素的位置
# find:在字串當中查詢某個字元或者字串的位置

# 會得到索引

  a = "wangyuze is coming"

  print(a.find('e')) # 7

  index = a.find('e')

  print(index) # 7

# 如果找的有兩個呢?  i,會得到第一個

  print(a.find('i')) # 9

# 如果是一個子串呢? ng

  print(a.find('ng')) # 2

# 如果找不到怎麼辦?會得到 -1 ,這是規定

  print(a.find('isnot')) # -1

# 如果子串不在一起,也是找不到,返回 -1

  print(a.find('wn')) # -1

# index 約等於 find
# 區別:index 找不到元素的時候,會報錯,find 找不到的時候返回-1

  print(a.index('ng')) # 2

  print(a.index('wn')) # ValueError: substring not found
  • count : 查詢元素的個數
  # count 統計某個字元出現的次數
  m_str = 'foweofpweef'
  print(m_str.count('o')) # 2

  song = "我愛你,我喜歡你,我..."
  print(song.count('我'))  # 3

  • replace : 替換字元
  # replace 替換
  song = "我愛你,我喜歡你,我..."

  print(song.replace('你', 'ta'))  # 我愛ta,我喜歡ta,我...

  • split : 字串分割

  # split  切分、切割   ==》 和 join 相反

  time_string = '2020/08/03'
  print(time_string.split('/'))  # ['2020', '08', '03']

  • format : 格式化輸出

  • upper : 將字母大寫


  # upper 所有字母都大寫
  name = 'yuze'
  print(name.upper())  # YUZE

  • lower : 將字母小寫

  # lower 所有字母都小寫
  name = 'JECK'
  print(name.lower())  # jeck

  • strip : 去掉兩邊的特殊字元,如果什麼都不傳,就是去掉空格或者換行符

  # strip  去掉兩邊的特殊字元,如果什麼都不傳,就是去掉空格或者換行符
  name = '   yuze wang   '
  print(name.strip()) # yuze wang
  print(name)

  cp = "&雨澤&哈哈&"
  print(cp.strip('&')) # 雨澤&哈哈

  • len : 計算字串長度

  # len 計算字串的長度
  name = 'yuzewang '
  print(len(name)) # 9

5、字串格式化輸出

  • format 格式化輸出

    • format() 功能強大,該函式把字串當成一個模板,通過傳入的引數進行格式化,並且使用 {} 作為特殊字元代替 %
    資料 格式 結果 描述
    5.11111 {:.2f} 5.11 保留小數點後兩位
    0.25 {:.2%} 25.00% 百分比格式
    aa {:<10} aa 左對齊(寬度為10)
    aa {:^10} aa 中間對齊(寬度為10)
    • format 字串的格式化
    ​```
    # 現在需要列印下面的格式:
    -------------------
    借條
    借款人:yuz
    債權人:double king
    金額:500
    -------------------
    
    loan_name = 'yuz'
    rich_man = 'double king'
    money = 500
    
    # # 方法一:
    # print("---------------------")
    # print('借條')
    # print('借款人:' + loan_name)
    # print('債權人:' + rich_man)
    # print('金額:' + str(money))
    # print('---------------------')
    # 
    # 
    
    # 方法二:
    # {} 表示佔坑符,佔位符
    # 位置一定要匹配,不能亂填順序
    # print("""
    # -------------------
    # 借條
    # 借款人:{}
    # 債權人:{}
    # 金額:{:.2f} 萬
    # -------------------
    # """.format(loan_name, rich_man, money))
    # 
    # 
    # # 方法三:
    # # f-string : python3.6 以後才支援
    # print(f"""
    # -------------------
    # 借條
    # 借款人:{loan_name}
    # 債權人:{rich_man}
    # 金額:{money} 萬
    # -------------------
    # """)
    
    
  • 傳統的格式化輸出 %

    符號 描述
    %s 格式化字串
    %d 格式化整數
    %f 格式化浮點數字,可指定小數點後的精度

(三)、列表和元組

1、列表

  • 列表的定義

    • 是一種資料型別,可以用來儲存多個資料
    • 列表用 [ ] 來標識
    • 列表內部的元素可以是任意型別的
    • 列表是使用最頻繁的資料型別之一
  • 列表的常見操作

    • 下標取值(索引取值):獲取某一個元素

    • 切片操作:獲取多個元素

      • 有步長的切片過程:先根據起始位置和終止位置,將內容切出來,然後再根據步長分為若干部分,然後將每部分的第一個元素拿出來,得出結果。
    • 修改元素的值:可以通過下標修改指定位置的元素。

      # 5 個人,5個大佬 , 使用列表
      big_boss = ['Demons', 'Go', 'EE', '上善若水', 'summer']
      print(big_boss)
      
      
      # 元素可以是任意的資料型別
      big_boss = ['Demons', 11, True, 33.33, 'summer']
      print(big_boss)
      
      big_boss = ['Demons', 11, True, 33.33, ['a','b','c']]
      print(big_boss)
      
      big_boss = ['Demons', 11, True, 33.33, ['a','b',['yuz',True]]]
      print(big_boss)
      
      
      # 索引: 獲取索引為 0 的元素
      print(big_boss[0]) # Demons
      print(big_boss[-1]) # ['a', 'b', ['yuz', True]]
      print(big_boss[-2]) # 33.33
      print(big_boss[2]) # True
      
      # 獲取 a
      print(big_boss[-1][0]) # a
      last_one = big_boss[-1]
      print(last_one[0]) # a
      
      # 獲取 'yuz'
      print(big_boss[-1][-1][0]) # yuz
      
      
      # 切片
      print(big_boss[:3]) # ['Demons', 11, True]
      
  • 列表巢狀

    • 列表中如果有多層巢狀,取值時需要一層一層的取值

      lst = [
          'a',
          'b',
          [1,2,3]
      ]
      
      print(lst[0]) # a
      
      print(lst[-1][1]) # 2
      
      

  • 列表的方法

    • 增:append 、insert 、 extend
    • 刪:pop 、 remove
    • 改:通過下標修改值
    • 查:index 、 count
    • 其他:reverse 、 sort
    方法 描述
    append 在列表的尾部加入一個元素
    insert 在指定位置插入一個元素
    extend 插入多個元素
    pop 刪除一個元素(預設從列表尾部刪除,也可以指定下標進行刪除)
    remove 刪除指定的元素(從前往後找)
    index 查詢元素的位置,找到第一個就返回結果
    count 統計元素的個數
    sort 將列表的元素進行排序
    reverse 將列表內元素反序(頭變為尾,尾變頭)
    # TODO:坑
    dalaos = ['隨風']
    
    new_dalao = dalaos.append('利己')
    print(dalaos) # ['隨風', '利己']
    
    # append() 返回 None
    print(new_dalao) # None
    
    # 再新增多個,['一罐','本本','可愛','美雪'] 新增到最後
    dalaos.extend(['一罐','本本','可愛','美雪'])
    print(dalaos)
    
    
    # TODO: 坑2 報錯:AttributeError: 'NoneType' object has no attribute 'append'
    new_dalao = dalaos.append('sfo').append('hello').append('sof')
    print(new_dalao)
    
    
    # 增加某個元素,修改的是原來的變數 lst
    lst = ['yuz', 'shanshan', 'rita']
    lst.append('裴綸')
    print(lst) # ['yuz', 'shanshan', 'rita', '裴綸']
    
    
    # insert 指定索引位置新增元素,不是獲取索引,不用[]
    lst.insert(1, '仙人球')
    print(lst) # ['yuz', '仙人球', 'shanshan', 'rita', '裴綸']
    
    
    # extend 新增多個,可以合併 2 個列表
    lst.extend(['tiger', 'f2'])
    print(lst) # ['yuz', '仙人球', 'shanshan', 'rita', '裴綸', 'tiger', 'f2']
    
    
    lst = [1,2,3]
    lst.append(3)
    print(f"第一次嘗試{lst}") # 第一次嘗試[1, 2, 3, 3]
    # lst.extend(3)
    # print(f"第二次嘗試{lst}") # 報錯:TypeError: 'int' object is not iterable
    lst.extend([3])
    print(f"第三次嘗試{lst}") # 第三次嘗試[1, 2, 3, 3, 3]
    
    
    
    a = [1,2,3]
    b = [4,5,6]
    
    # b 是作為一個整體,一個元素,新增到 a 當中
    # a.append(b)
    # print(a) # [1, 2, 3, [4, 5, 6]]
    
    # b 是拆開裡面元素,作為多個元素,新增到 a 當中
    a.extend(b)
    print(a) # [1, 2, 3, 4, 5, 6]
    
    """列表的刪除
    - remove
    - delete
    - pop
    
    """
    
    # remove: 在列表當中刪除指定的值
    big_boss = ['糖', '木易', '均價']
    big_boss.remove('木易')
    print(big_boss) # ['糖', '均價']
    
    
    # delete 異類:儘量不要用
    # del big_boss[0]
    # print(big_boss) # ['均價']
    
    
    # pop  0 代表索引為 0
    big_boss.pop(0)
    print(big_boss) # ['均價']
    
    # 獲取索引為 0 的值
    print(big_boss[0])
    
    
    big_boss.append('木易')
    print(big_boss) # ['均價', '木易']
    
    """列表的修改
    
    lst[0] = 1
    """
    
    lst = [1,2,3]
    
    lst[1] = 'a'
    print(lst) # [1, 'a', 3]
    
    
    lst[1],lst[2] = 'c', 'd'
    print(lst) # [1, 'c', 'd']
    
    
    lst[1:] = 5,6
    print(lst) # [1, 5, 6]
    
    """列表的方法
    - index
    - count
    - sort
    - reverse
    - clear
    
    """
    
    lst = [4,5,6,5]
    
    # # 統計
    # print(lst.count(5)) # 2
    #
    # # index 查詢得到第一次出現的索引值
    # print(lst.index(5)) # 1
    #
    # # sort 排序
    # print(lst.sort()) # None
    #
    # lst.sort()
    # print(lst) # [4, 5, 5, 6]
    #
    #
    # # reverse 反向,倒序 ,  相當於 [::-1]
    # lst.reverse()
    # print(lst) # [6, 5, 5, 4]
    
    
    # 反向排序
    lst.sort(reverse=True)
    print(lst) # [6, 5, 5, 4]
    
    
    # clera 清除一個列表
    lst.clear()
    print(lst) # []
    

2、元組

  • 元組的定義:

    • 元組定義在小括號中,元組內部的資料:它支援數字,字串甚至可以包含元組(即巢狀)
  • 元組的常見操作

    • 下標取值:元組內部的資料是有序的,可以通過下標獲取對應的元素
  • 注意點

    • t = () 空元組
    • t = (1,) 只有一個資料的時候要注意加逗號
    • 元組的值不可以修改,是屬於不可變資料
  • 元組的方法

    • count : 查詢元素的個數
    • index :查詢元素下標
    tuple_yuz = ('yuz','一罐',['閒人','七七','小驕傲'])
    # 修改的是元組的元素,元組的元素是列表
    # tuple_yuz[2] = ['新列表']
    # print(tuple_yuz) # 不能修改元組的元素
    
    # 為什麼這裡可以改??
    # 元組的不可變是相對的,不是說裡面所有的內容都完全不能變
    # 只要看索引的前面是不是一個可變的型別
    tuple_yuz[2][0] = ['新列表']
    print(tuple_yuz)
    
    
    tuple_yuz = ('yuz','一罐',{'tuple':'yuze'})
    # 索引前面是元組,代表我們要修改的是元組的元素,不可以
    # tuple_yuz[2] = 'hello world'
    
    # tuple_yuz[2] 是字典,可變型別,可以直接修改
    tuple_yuz[2]['name'] = 'hello world'
    print(tuple_yuz)
    
    
    # 索引前yuz是列表,可以改變
    yuz = ['yuz','一罐',('四葉草','曉峰')]
    yuz[2] = 'hello'
    print(yuz)
    
    # yuz[2]是元組,不可變
    yuz[2][1] = 'youxi'
    
    tuple_demo = ()
    print(tuple_demo)
    
    
    # TODO:坑 ,一個元素的元組表示,不是一個元組,而是去掉括號後的原始資料型別
    # tuple_demo_2 = (1)
    # print(tuple_demo_2)
    
    # 如果想表示一個元素的元組,記得務必在元素後面加一個逗號
    # tuple_demo_3 = (1,)
    # print(len(tuple_demo_3))
    
    tuple_demo_4 = (1,3,4,5,5,)
    print(len(tuple_demo_4))
    tuple_demo_5 = 1
    print(tuple_demo_5)
    
    
    # 元組解包
    family_name,name = ('wang','yuze')
    # family_name,name = ('wang','yuze','hello') # 值要一一對應,否則會報錯
    print(family_name)
    print(name)
    
    a,b = 3,4
    print(a)
    print(b)
    
    
    family_name,name,*other = ('wang','yuze','hello','world')
    print(family_name)
    print(name)
    print(*other)
    

3、字串、列表、元組總結

  • 序列型別:
    • 字串、列表、元組,統稱為序列型別資料(內部的元素是有順序的)
  • 通用操作:
    • 下標取值:
    • 切片:
    • 獲取元素總數: len()

(四)、字典和集合

  • 問題:
    • 使用一個列表儲存了一個學生資訊,姓名,年齡,電話號碼,stu = ['小明', '18', '13812341234']
    • 問題一:當前如果電話號碼寫錯了,怎麼修改
    • 問題二:當前列表中有10個設定100個元素,不知道電話號碼具體的下標,怎麼修改電話號碼

1、字典

  • 字典的定義:

    • 也是用來儲存多個資料的

    • 字典:字典用 {} 來標識

    • 字典能夠表示元素更具體的意思,每個元素表示的意義是什麼,可以通過 key 命名

    • 字典的結構:就是將它看做是一個 {key:value} 鍵:值 對的集合,鍵必須是唯一的(在一個字典中)

    • 空字典 : {}

    • 字典定義的方式:

      # 方式一:
      dic = {'name':'musen', 'age':18}
      
      # 方式二:
      dic = {name = 'musen', age = 18}
      
  • 注意點:

    • 字典中的鍵必須是唯一的
    • key 不能出現重名,在一個字典當中,key 之間是不一樣的
    • key 不能變的,列表是不能作為 key 的
    • 可變型別資料:字典定義後可以修改內部元素
    • 注意點:字典的鍵必須是不可變型別的(一般情況下都是字串),值可以是任意型別的資料(字典,元組,列表等等都可以)
  • 字典的增刪改查

      • 通過指定鍵去新增相應的值
        dic[key] = value

      • update() : 將一個字典的所有元素更新到另一個字典中

      # 簡單理解
      dic.update({'a':1, 'b':2})
      
      
    • 改:通過指定鍵去修改對應的值
      dic[key] = value

      • pop() : 刪除指定的鍵,刪除的鍵不存在會報錯(避免錯誤可以新增預設值)
        dic.pop(key)

      • popitem() : 刪除一個鍵值對,刪除最後一個新增的元素

        • 之前版本是隨機刪除一個元素,python3.7新特性,刪除最後新增的元素
      • 關鍵字 del : 通過鍵刪除

        del dic[key]

    • get() : 獲取鍵對應的值
    • keys() : 獲取所有的鍵,可以用 list 將結果轉換成列表
    • values() : 獲取所有的值,可以用 list 將結果轉換成列表
    • items() : 獲取所有的鍵值對,可以用 list 將結果轉換成列表,列表中每個鍵值對組成一個元組。
    # 列表:當每個元素有具體的意義,你又想去單獨獲取的時候,可讀性不強
    beisheng = ['星際穿越', '蜘蛛俠', '上海堡壘', '分手大師', '前任3']
    print(beisheng[2])
    
    
    # 字典:key: 元素的名稱, value: 元素的值 ,  鍵值對:成對
    # 用 {} 在最外面
    # key: value, key1: value1
    beisheng = {'favor':'星際穿越','hate':'蜘蛛俠','first':'上海堡壘','last':'分手大師','twice':'前任3'}
    
    print(beisheng['hate']) # 蜘蛛俠
    
    
    # 重名的key
    beisheng = {'favor':'星際穿越',
                'hate':'蜘蛛俠',
                'first':'上海堡壘',
                'favor':'分手大師',
                'twice':'前任3'}
    # favor 後面的值會覆蓋前面的值
    print(beisheng['favor']) # 分手大師
    
    print(beisheng) # {'favor': '分手大師', 'hate': '蜘蛛俠', 'first': '上海堡壘', 'twice': '前任3'}
    
    
    # key 不能是列表
    # beisheng = {'favor':'星際穿越',
    #             ['hate']:'蜘蛛俠',
    #             'first':'上海堡壘',
    #             'favor':'分手大師',
    #             'twice':'前任3'}
    # print(beisheng) # 報錯:TypeError: unhashable type: 'list'
    
    
    # 鍵為數字: 沒有意義,不建議使用
    beisheng = {1:'星際穿越',
                3:'蜘蛛俠',
                2:'上海堡壘',
                5:'分手大師',
                4:'前任3'}
    print(beisheng) # {1: '星際穿越', 3: '蜘蛛俠', 2: '上海堡壘', 5: '分手大師', 4: '前任3'}
    
    beisheng = {'favor':'星際穿越',
                'hate':'蜘蛛俠',
                'first':'上海堡壘',
                'last':'分手大師',
                'twice':'前任3'}
    
    # 獲取,查
    print(beisheng['hate'])
    # 字典沒有索引和切片
    
    
    # 修改
    beisheng['hate'] = '蝙蝠俠'
    print(beisheng) # {'favor': '星際穿越', 'hate': '蝙蝠俠', 'first': '上海堡壘', 'last': '分手大師', 'twice': '前任3'}
    
    
    # 新增, 和修改是一樣的
    # 什麼時候是修改,什麼時候又是新增?
    # 看 key:當 key 已經存在的時候,是修改,當之前沒有這個key,就是新增。
    beisheng['scared'] = '貞子'
    print(beisheng)
    
    beisheng['scared'] = '午夜凶鈴'
    print(beisheng)
    

2、集合

  • 定義:

    • 集合中的元素不能重複
    • 花括號 或 set() 函式可以用來建立集合
  • 注意:

    • 要建立一個空集合你只能用 set() 而不能用 {} ,因為後者是建立一個空字典
  • 集合的方法:

    • 增加元素 : add
    • 刪除元素 :pop , remove
    • 自動化測試中很少用集合來存放資料,更多內容請自行擴充套件
  • 集合的重要應用場景:去重

  • 集合的交集、並集、差集

    • a & b : 集合 a 和 b 中都包含了的元素
    • a | b : 集合 a 或 b 中包含的所有元素
    • a - b : 集合 a 中包含而集合 b 中不包含的元素
    # 集合不是鍵值對
    # 集合是無序的
    # 不能通過索引獲取
    # 重複的元素直接丟掉,集合目前我們使用的最多的功能就是去重
    set_yuz = {'yuz','魯西西','閒人','yiguan'}
    print(set_yuz)
    # print(set_yuz[1]) # 會報錯
    print(len(set_yuz))
    
    # 去重
    set_yuz = list(set(['yuz','魯西西','閒人','yuz']))
    print(set_yuz)
    
    
    # split 分割
    # a = 'hello world'
    # b = a.split('w')
    # print(b)
    
    a = 'hello/world/sofo/sooof'
    b = a.split('/',1) # 數字1代表分割一次
    print(a) # a 是字串,不會變
    print(b)
    

(五)、資料型別相互轉換

1、字串的轉化

  • 字串轉換成列表

    • 字串轉換成list 的時候,str可以作為迭代物件,直接放入;也可以使用split對字串進行切割。然後返回list
    s = '1ab1cd'
    print(list(s))  # ['1', 'a', 'b', '1', 'c', 'd']
    print(s.split('1')) # ['', 'ab', 'cd']
    

  • 字串轉換成元組

    s = '1ab1cd'
    print(tuple(s)) # ('1', 'a', 'b', '1', 'c', 'd')
    

  • 字串轉換成字典

    a='1ab1cd'
    b='123456'
    print(zip(a,b)) # <zip object at 0x00000000022952C8>
    print(dict(zip(a,b))) # {'1': '4', 'a': '2', 'b': '3', 'c': '5', 'd': '6'}
    
    
    a='1ab1cdd4e5'
    b='123456'
    print(zip(a,b)) # <zip object at 0x00000000022952C8>
    print(dict(zip(a,b))) # {'1': '4', 'a': '2', 'b': '3', 'c': '5', 'd': '6'}
    

  • 字串轉換成集合

    a='1ab1cd1d'
    print(set(a)) # {'1', 'a', 'c', 'b', 'd'}
    

2、列表的轉化

  • 列表轉換成字串

    • 列表裡如果有int型別,字典,元祖,列表,則join方法不可用
    list = ["3","d","aaa"]
    print("".join(list)) # 3daaa
    print(" ".join(list)) # 3 d aaa
    print("!".join(list)) # 3!d!aaa
    

  • 列表轉換成元組

    list = ['1','2','3','a',(1,2,3),1,[1,2],{"a":1}]
    print(tuple(list)) # ('1', '2', '3', 'a', (1, 2, 3), 1, [1, 2], {'a': 1})
    

  • 列表轉換成字典

    list1 = ['1','2','3','4','a',(1,2,3),5,6]
    list2 = ['a','b','c','d','e','f',[1,2],{"g":"h"}]
    dict1 = dict(zip(list1,list2))
    print(dict1)
    # {'1': 'a', '2': 'b', '3': 'c', '4': 'd', 'a': 'e', (1, 2, 3): 'f', 5: [1, 2], 6: {'g': 'h'}}
    

  • 列表轉換成集合

    list = ['1','2','3','3']
    print(set(list)) #{'3', '1', '2'}
    

3、元組的轉化

  • 元組轉換成字串

    • 元組裡如果有int型別,字典,元祖,列表,則join方法不可用
    tuple = ('1','2','3','4','2','a')
    print(''.join(tuple)) # 12342a
    
  • 元組轉換成列表

    tuple = (1,2,3,4,5,'2','a')
    print(list(tuple)) # [1, 2, 3, 4, 5, '2', 'a']
    
  • 元組轉換成字典

    tuple1 = ('1', '2', '3', '4',111,(11,22,33),"")
    tuple2 = ('a', 'b', 'c', 'd','e','f','h','g','i','j','k')
    dict1 = dict(zip(tuple1, tuple2))
    print(dict1) # {'1': 'a', '2': 'b', '3': 'c', '4': 'd', 111: 'e', (11, 22, 33): 'f', '': 'h'}
    
  • 元組轉換成集合

    tuple1 = ('1','2','3','4',4,'4',4,1)
    print(set(tuple1)) # {1, 4, '3', '1', '2', '4'}
    

4、字典的轉化

  • 字典轉換成字串

    • 對於生成字串,需要先生成list和tuple,然後再由list和tuple生成str
    dict1 = {1:'a',2:'b',3:'c'}
    
    list1 = list(dict1.values())
    print("".join(list1)) # abc
    
    tuple1 = tuple(dict1.values())
    print("".join(tuple1)) # abc
    
  • 字典轉換成列表/元組/集合

    • 字典可以使用 dict.keys() 和 dict.values() 返回迭代器,通過list和tuple直接生成列表和元祖
    dict1 = {1:'a',2:'b',3:'c'}
    print(list(dict1.keys())) # [1, 2, 3]
    print(list(dict1.values())) # ['a', 'b', 'c']
    
    print(tuple(dict1.keys())) # (1, 2, 3)
    print(tuple(dict1.values())) # ('a', 'b', 'c')
    
    print(set(dict1.keys())) # {1, 2, 3}
    print(set(dict1.values())) # {'a', 'b', 'c'}
    
    print(tuple(dict1.items()))  #生成元祖為單位的元祖
    # ((1, 'a'), (2, 'b'), (3, 'c'))
    print(list(dict1.items()))  #生成元祖為單位的列表
    # [(1, 'a'), (2, 'b'), (3, 'c')]
    print(set(dict1.items()))   #生成元祖為單位的集合
    # {(2, 'b'), (3, 'c'), (1, 'a')}
    

5、集合的轉化

  • 集合轉換成字串

    • 集合是無序的,每次轉換成的字串值都不一定一樣,也可以先轉為列表或者元祖,再轉換成字串
    set1 = {"1","2","ac"}
    print("".join(set1)) # 2ac1
    print(type("".join(set1))) # <class 'str'>
    
  • 集合轉換成列表/元組

    set1 = {1,2,3,4,5,6}
    print(list(set1)) # [1, 2, 3, 4, 5, 6]
    print(tuple(set1)) # (1, 2, 3, 4, 5, 6)
    
  • 集合轉換成字典

    • 無意義的對映,不推薦
    set1 = {1,2,3,4,5,6}
    set2 = {'a','b','c','d'}
    print(dict(zip(set1,set2)))
    # {1: 'd', 2: 'a', 3: 'b', 4: 'c'}
    

三、控制流程

(一)、條件語句

  • if條件判斷

    • 分支結構,常用的表現方式:
      • if(條件表示式):......
      • if(條件表示式):......else:......
      • if(條件表示式):......elif(條件表示式):......elif(條件表示式):......else:
# if的寫法(else可以省略)
if (條件表示式):
		pass
else:
		pass

  
if (條件表示式):
		pass
elif (條件表示式):
		pass
else:
		pass


# 例如:
username = "yuze"
if username == "yuze" or username == "yuzewang":
		#縮排表示條件滿足以後需要執行的子程式碼,是一個分支
		print("登入成功")
elif username == ""
		print("請輸入使用者名稱")
elif username == "Demo"
		print("沒有該使用者")
else
		print("登入失敗")
  • if語句用於驗證某個條件

    • 當條件為真時,執行if下面的程式碼塊,否則執行else下面的程式碼塊
    • 條件當中,只要執行了一個分支,其它分支就不會繼續執行了
      • 條件表示式:要得到的值是一個bool型別,True, False
  • 使用if需要注意的點

    • 所有分支流必須以if開頭
    • 語句中的else可以省略
    • if與elif後面必須加條件表示式,else後面不能加條件表示式
    • 一個判斷分支下只有一個if,一個else,可以有多個elif
    • 分支下按順序執行程式碼,只要執行了一個分支下的程式碼,其他的分支則都不會執行

(二)、程式debug除錯

  • 是暫停程式碼的執行去獲取現在的資料狀態
    • print
    • pycharm中的debug
      • 先打斷點
      • 再執行debug
      • 下一步按鈕
      • 檢視資料
  • 打斷點,是告訴程式我應該在哪裡暫停

(三)、while迴圈

  • 迴圈控制流

    • 迴圈語句,用於驗證某個條件
    • 當條件為真時,執行迴圈下的程式碼塊,否則結束迴圈
    • 分類:
      • while 迴圈
      • for 迴圈
  • while迴圈作用:用來重複執行某個操作

  • while 語法

while 判斷條件:
		執行程式碼

# 例如:

times = 0
while times < 999:
		print("我說了{times}次")
		times = times + 1

      
continue: 表示手工進入下一個迴圈體,進入下次迴圈


break:表示手工強制退出整個while迴圈


(四)、for迴圈

  • 作用:

    • 用來遍歷物件
    • 從物件的第一個元素到最後一個元素,依次訪問
    • for迴圈會自動+1
  • 語法

    • for 元素 in 資料集合:執行程式碼
    • 資料集合可以是:列表,元組,字典,字串,也可以是指定的資料範圍
    • for迴圈巢狀,子迴圈執行完,才會回到母迴圈執行
for 迭代變數 in 字串|列表|元組|字典|集合:
   	程式碼塊

# 例如:

add = "http://c.biancheng.net/python/"
#for迴圈,遍歷 add 字串
for ch in add:
   	print(ch,end="")   
   
   
continue:手工進入下一個迴圈體,進入下次迴圈    

break:手工強制退出整個while迴圈
  • break

    • 常用在迴圈結構中
    • 在迴圈中遇到break,就跳出迴圈
  • continue

  • 常用在迴圈結構中

  • 在迴圈中遇到continue,就跳出本次迴圈,繼續下一次迴圈

(五)總結知識點

  • for經常用到的場景:如果有一個現成的列表,字串,字典,就用for
  • while經常用到的場景:不知道什麼時候結束迴圈
  • 同時獲取列表的索引和值
for i,value in enumerate(list):
		print(i, value)
  • 同時獲取字典的鍵和值(常用)
for k,v in mdict.items():
		print(k, v)
  • 獲取所有的value
for value in mdict.values():
		print(value)
  • 獲取所有的key
for key in mdict.keys():
		print(key)
		  	
for k in mdict:
		print(k)
  • range() 函式

    • 表示迴圈某一個資料段
    • range(start,end,step),與切片類似,包前不包後
    • 列印100遍
    for i in range(100):
    		print(i)
    

四、函式和函式引數

(一)、函式定義和呼叫

1、函式的定義

  • 函式的概念:以數學函式來理解

  • 作用:傳入一個自變數,會得到一個另外的變數,這個變數會根據自變數變化而變化

  • 用於儲存一段程式碼。 是封裝

  • 定義函式關鍵字:def

  • 為什麼要寫函式:方便好用、複用性高

  • 函式名:屬於識別符號,遵循識別符號的命名規則:

    • 函式的名稱是一個識別符號:數字、字母、下劃線,不能是內建關鍵字
    • 函式名遵循蛇形命名:下劃線命名
    • 函式名稱要見名知義
    • 函式命名的重要性:函式的名稱會告訴讀程式碼的人:這個函式的作用是什麼
  • 語法:

    def 函式名(引數):
    		函式內部功能程式碼一
        函式內部功能程式碼二
        函式內部功能程式碼三
        函式內部功能程式碼四
        
        
    def add(a,b):
    		print(a+b)	
    
    
  • 函式中的程式碼如何執行?

    • 函式定義時,函式的程式碼不會被執行,只有當函式被呼叫時,函式中的程式碼才會被執行
  • 不要在一個檔案中定義兩個同名函式,後面的會覆蓋前面的

def add (a,b):
		print(a+b)
def add (a,b):
		print(a-b)
		
add(1,2)  # -1

2、函式的呼叫

  • 使用函式的過程叫做呼叫函式;呼叫的時候會給變數賦值,即變數 = 值

  • 呼叫方法:

    函式名()

  • 函式的相互呼叫

    • 在函式中呼叫另外一個函式
    • 函式呼叫是去執行函式體內部邏輯
    • 避免兩個函式相互呼叫
    • 不要呼叫自己

(二)、函式的返回值

  • return 的作用:
    • 返回值數目 = 0;返回 None
    • 返回值數目 = 1:返回object
    • 返回值數目 > 1:返回tuple
  • 疑問:為什麼要用return?什麼時候用return?
    • 根據需求,當需要返回的時候就返回,不需要返回的時候就不返回。
  • 注意點:
    • 1、return 是用來給函式返回結果的。
    • 2、當函式執行到return 時函式執行結束。
    • 3、函式沒有定義return,預設的返回值為None
  • 現在有兩件事,寫成兩個函式

(三)、函式引數

  • 1、引數的定義

    • 函式名後面的括號彙總定義引數
  • 2、形參與實參

    • 在函式定義的時候出現,是變數名,是自己定義的
    • 呼叫時實際傳遞的引數為:實參,是函式呼叫時出現的,實際引數是將要賦給變數名(形參)的值
    • 實參和形參要配對,成對出現的,下面情況都是不行的
      • 只有實參,沒有形參
      • 只有形參,沒有實參
    def add (a,b):
    	print(a+b)
    	return(a+b)
    add(1,2)  # a,b是形參, 1,2 是實參 
    
  • 位置引數

    • 函式的形參和實參是成對出現的,一一對應的
    • 函式呼叫的時候一定要檢查好引數的個數
    • 位置引數概念
      • 形參和實參的這種位置關係叫位置引數
    def add (a,b):
    	print(a+b)
    	return(a+b)
    add(1,2)  # 1對應a, 2對應b
    
  • 關鍵字引數

    • 關鍵字引數,函式呼叫的時候,給實際引數貼標記,標記是形參的變數名
    • 通過關鍵字引數,可以不按順序配對
    • 關鍵字引數要放在位置引數的後面
    • 關鍵字引數的作用:當引數很多時,可以使用
    def add (a,b):
    	print(a+b)
    	return(a+b)
    add(b=3,a=2)
    
  • 預設引數

    • 在函式定義的時候,給形式引數一個預設的值
    • 呼叫函式的時候,可以不用賦值給預設引數
    • 使用預設引數:可以少些實際引數
    • 放在位置引數後面
    def add (a,b=8):
    	print(a+b)
    	return(a+b)
    
  • 不定長引數

    • 不定長參數列示方式: * **
    • * 當在一個形參前加*,他會收集所有剩下沒有配對的實際引數(位置引數),把剩下的資料組成一個元組
    • *args 存放很多位置引數
    def add (a,*b):
    	print(a)
    	print(b) 
    add(1,2,3,4)   # 1,(2,3,4)
    
    def add (a,*b):
    	print(a)
    	print(b)
    add(1,2,3,4,c=1) #報錯:預設引數要放到位置引數後面,不定長引數放到位置引數後面
    
  • **只能收集關鍵字引數

  • **kwargs 存放很多關鍵字引數

  • 將資料轉換為字典的形式

def add (a,**b):
  	print(a)
  	print(b)

add(1,c=1,d=2)  # 1  {'c': 1, 'd': 2}
  • 不定長引數的作用

    • 在引數定義的時候,不知道有多少個實際引數(關鍵字引數)
  • 拆包:

    • 列表、元組拆包
      • 會拆成位置引數
      • 函式定義當中args 表示不定長的位置引數,在呼叫的時候,叫做拆包、解包
      • 呼叫的時候,把 一個列表或元素變數傳入函式,在前面加,就可以比那成多個值
    def marry(male,female):
    		print(male)
    		print(female)
    
    couple = ("老王","小星星")
    
    marry(*couple)
    
    
    • 字典拆包
      • 會拆成關鍵字引數
    couple = {"male":"小王","female":"老劉"}
    
    marry(**couple)
    
    

(四)、函式作用域

  • 是區域性作用域
    • 在定義函式時,設定的變數為區域性變數
    • 區域性變數不能在全域性作用域獲取
    • 函式內部區域性作用域可以用全域性變數
    • 在函式外部不能修改函式內部的變數
    • 在函式內部可以修改全域性變數,不過需要用global宣告是全域性變數 例如:global c

(五)、內建函式

  • print :輸出

  • input :輸入

  • type :檢視資料型別

  • range :生成資料

  • id :獲取資料記憶體地址

  • int、float、str、bool、list、dict、tuple、set :代表對應的資料型別,轉換資料型別

  • max :獲取最大的值,可以傳多個引數,可以傳列表

  • min :獲取最小的值,可以傳多個引數,可以傳列表

  • sum :求和

  • enumetate:

    # enumerate() 將列表中的元素及其位置轉換為成對的元組
    m_list = ['aa', 'bb', 'cc', 'dd']
    print(list(enumerate(m_list)))
    # [(0, 'aa'), (1, 'bb'), (2, 'cc'), (3, 'dd')]
    
    print(list(enumerate(m_list, start = 1)))
    # [(1, 'aa'), (2, 'bb'), (3, 'cc'), (4, 'dd')]
    
  • eval :可以去掉一個字串的引號

    m_str = "6>7"
    print(m_str)
    print(eval(m_str))   # False
    m_str = '{"username":"yuz","age":18}'
    print(m_str)          # {"username":"yuz","age":18}
    print(type(m_str))    # <class 'str'>
    print(eval(m_str))    # {'username': 'yuz', 'age': 18}
    print(type(eval(m_str))) # <class 'dict'>
    
  • filter :過濾某些資料 filter(呼叫函式,列表)

li = [2,3,4,5,6,7]
def get_odd(value):
    if value % 2 == 0:
        return True
    return False
    
res = filter(get_odd, li)
print(list(res)) # [2, 4, 6]
  • map :
li = [2,3,4,5,6,7]

def square(value):
    return value ** 2

res = map(square, li)
print(list(res))  # [4, 9, 16, 25, 36, 49]
  • zip :
li_1 = ["yuz","hello","world"]
li_2 = [43,12,15]

print(list(zip(li1,li2)))  # [('yuz', 43), ('hello', 12), ('world', 15)]

a = zip(li1, li2)
print(dict(a))  # {'yuz': 43, 'hello': 12, 'world': 15}

(六)、模組和包

  • 模組

    • 模組,就是一個帶 .py 字尾的python 檔案,一個模組裡面會有很多的函式,類
    • 模組名稱:是一個識別符號,符號識別符號命名規則
      • 數字、字母、下劃線,不能以數字開頭,不能是關鍵字
      • 模組名稱命名一般是使用下劃線的形式命名,駝峰, d1_review.py
      • 模組名稱不能和 python 內建的模組名稱重合
    • 模組作用:
      • 有邏輯的組織python程式碼
      • 把相關功能的程式碼寫到一個模組裡能讓程式碼更好用,更易懂
    • 包,package,就是一個python檔案的資料夾,裡面會有一個或多個模組
    • 包含一個_init_.py 模組的資料夾,這個模組可以什麼都不定義,可以只是一個空資料夾
    • 標準庫,第三方庫,實現特定功能的程式碼集合,一個模組,也可以是一個包
    • python3 新版本,不帶_init_.py 同樣可以作為包使用
  • 模組匯入

    • 是模組間變數和函式的互相使用 ,需要使用 import 的關鍵字

    • import ... 後面只能跟 模組,不能跟函式,變數

    • from .. import ... 後面可以跟模組,函式,類,變數

    • 匯入自己的模組,別人的第三方模組,一般使用from import ,不用import..

      • google內部約定,匯入模組只匯入模組這一層,然後使用 模組名.函式名() 來呼叫函式

        from class_9_file import demo01
        
        demo01.test01_fun()
        
      • import .. 呼叫函式的時候需要些很長的字首,比較麻煩

    • 不建議使用:from... import *

      • 匯入模組或者包裡面,所有的類、函式、變數
      • 匯入所有,如果重命沒有解決方法
    • as 重新命名 - 避免同名函式衝突

      • 匯入時匯入到模組這一層,使用時使用模組名.函式名

      • 使用別名

        • 別名就是重新命名,就是原函式名很長,為了方便使用函式
        from class_9_file import demo01 as d
        
        d.test01_fun()
        
    • 不要用相對匯入,要絕對匯入,就是從根目錄開始匯入

五、檔案及路徑

(一)、檔案

1、開啟檔案和關閉檔案

  • 開啟檔案,使用內建函式 open()

    • open(" path/檔名.字尾 “)
  • 特別注意:開啟檔案不管進行什麼操作後,一定要關閉檔案,否則會出現資料不對,或者寫入內容不生效,檔案無法再次被開啟等情況

    f = open("python32.txt")
    f.close()
    
  • 為了避免忘記關閉檔案,可以使用with語句,操作完成後會自動關閉檔案

    with open('python32.txt','r',encoding='utf8') as f:
        print(f.read())
        
    with open('python32.txt','a',encoding='utf8') as f:
        print(f.write())
    
  • 不在同一路徑下要用絕對路徑,windows要加 r 防止轉義,有反斜槓,mac不用加

    with open(r'J:\學習資料\Study\PythonAndSelenium\檸檬班python自動化課程\python32_API\class_09_file\python32.txt') as f:
      print(f.readline())
    

2、讀取檔案

  • mode 開啟方式

    • r 以只讀方式開啟檔案(預設),一般用於文字檔案,如:txt。檔案指標預設放在檔案開頭
    • b 以二進位制格式開啟檔案。一般用於非文字檔案,如:圖片、視訊
    • rb 以二進位制的形式開啟並讀取
  • read() 讀取

    with open("python32.txt", mode = 'r', encoding = 'utf8') as f:
        print(f.read())
        
        
    with open('1.png', mode= 'rb') as f:
        print(f.read())
    
  • readline() 讀取一行

    with open('python32.txt', encoding = 'utf8') as f:
        print(f.readline())
    

  • readlines() 讀取所有行,會以列表的形式展示

    with open('log.txt', encoding = 'utf8') as f:
        print(f.readlines()) # 可以顯示換行符
    

3、寫入檔案

  • mode 寫入方式

    • w 新建寫入
      • w比較危險,如果之前已經有同名的檔案,用w會覆蓋之前的內容,w只能用於新建寫入
    • a 追加寫入
      • 如果檔名不存在,是先新建再寫入;如果檔名存在,則為追加
    • wb 以二進位制開啟一個檔案用於只寫
      • 如果檔名存在,則覆蓋,不存在,則新建寫入
    • ab 以二進位制開啟一個檔案用於追加
      • 如果檔案存在,檔案指標會放在檔案結尾處
    with open('python32.txt', mode = 'w', encoding = 'utf8') as f:
        f.write('裴綸')
        
    with open('python32.txt', mode = 'a', encoding = 'utf8') as f:
        f.write('哈哈哈')
    
    • + 表示可以同時讀寫某個檔案
      • r+ 可讀,可寫
      • w+ 可讀,可寫
      • a+ 可讀,可寫

(二)、路徑

1、路徑

  • sys . path 包含專案開始根目錄路徑和 python 內建的目錄路徑

    • 模組匯入的搜尋路徑: sys.path
      • 模組匯入不了時可以用來檢查
      • python去查詢包或模組,相當於python裡的地圖
      • 返回的是一個列表
  • os 是 python 內建的模組需要用 import 匯入: import os

  • 找模組

    • 專案開始根目錄
    • python內建目錄
    • 不建議將寫的模組存放在python的安裝目錄下
    • python目錄主要是放外部的庫或第三方的模組

2、路徑處理

  • python中一般不直接寫入絕對路徑, 而是通過程式碼獲取

  • 獲取當前檔案的路徑:

    abs_path = os.path.abspath(_file_)

    _file_ 表示執行的檔案的名稱

  • 獲取當前檔案的目錄路徑: 兩種寫法,用第一種絕對路徑

    dir_name = os.path.dirname(abs_name)

    dir_name = os.path.dirname(_file_)

  • 獲取不與當前檔案同一個目錄下的檔案路徑

    • 1 .先獲取當前檔案的絕對路徑
    • 2 .獲取當前檔案的目錄路徑
    • 3 .當前檔案的目錄路徑和該檔案拼接
    比如,獲取pac01 下面的 demo.txt:
    txt_file_path = os.path.join(dirname, 'pac01', 'demo.txt')
    
    讀取圖片檔案(二進位制格式)
    dir_name = os.path.dirname(os.path.abspath(file))
    png_pic = os.path.join(dir_name,'1.png')
    f = open(png_pic,mode='rb')
    print(f.read())
    f.close()
    
    

3、路徑操作

  • os.path.abspath() 獲取絕對路徑

  • os.path.dirname() 獲取檔案/目錄所在路徑

  • os.path.join(a, b) 連線兩個部分的路徑,組成一個完整路徑

  • os.getcwd() 獲取當前工作路徑

  • os.chdir() 切換工作路徑

  • os.mkdir() 在某個目錄下建立一個新目錄

  • os.rmdir() 刪除一個目錄

  • os.listdir() 獲取當前路徑下的目錄,返回列表格式資料

  • os.path.isdir() 判斷當前檔案是否是目錄,返回布林值

  • os.path.isfile() 判斷當前檔案是否是檔案,返回布林值

六、異常

(一)、異常處理

  • 異常
    • 當程式執行中檢測到一個錯誤時,無法繼續執行,出現一些錯誤提示,這就是異常。
    • 程式遇到異常不會再執行,我們要改變程式碰到異常的行為

(二)、異常型別的捕獲

  • 語法一:try...except....

    • 程式先執行try中的程式碼,一旦try中某個程式碼報錯, 會直接跳到except,try剩下的程式碼不會執行

      try:
        	 要執行的可能發生異常的程式碼
      except:
        	 程式發生異常後,你希望程式做的事情
      
      try:
      		1/0
      except IndexError as e: 
      		print(e)
      # 其中as e可以在後面用來展示異常資訊,但不能展示異常型別
      
  • 語法二:try...except....finally

    try:
    		1/0
    except ZeroDivisionError as e:
    		print("不能除以0")		
    finally:
    		print("無論異常與否,都會繼續執行的程式碼")	
    
    # 執行結果:
    # 不能除以0
    # 無論異常與否,都會繼續執行的程式碼
    
  • try...except...else

try:
	1 / 0
	print("正常執行的程式碼")
except ZeroDivisionError as e:	
	print("不能除以0")	
else:
	print("程式碼沒有報錯才會執行")
	print("正常執行的程式碼的後面部分")
# 執行結果:
# 不能除以0

(三)、多異常型別的捕獲

  • 多種異常出現時,可以統一處理的就用下面的方式一,處理方式不一樣的就用方式二
方式一:
try:
	{'name':'yez'}['age']
	a = 1/0
	lst = ['yz','yr']
	lst[3]
except(ZeroDivisionError, IndexError, KeyError) as err:
  print(err)
	print('hello')  
except ImportError as e:
	print()
    
    
方式二:
try:
  {'name':'yez'}['age']
  a = 1/0
	lst = ['yz','yr']
	lst[3] 
except ZeroDivisionError as err:
	print(err)
except IndexError as err:
	print('index error')
except KeyError:
	print('key error')  

(四)、丟擲異常

  • raise 主動丟擲異常

    def adult_add(a, b):
      # 兩個數相加, a, b 一定要大於18, 否則就不能執行
      if (a < 18) or (b < 18):
    		raise ValueError('引數必須大於18')
      c = a + b
      return c
    print(adult_add(3, 4))
    print('函式執行完成。')  # 上面一行報錯,這行不會打
    
    try:
    	adult_add(3, 4)  
    except:
    	print('函式執行完成。')  # 結果會列印:函式執行完成。
    

(五)、斷言 assert

  • 斷言: assert

  • 斷言的作用:判斷真假

  • 斷言的時候,如果斷言成功,程式繼續執行

  • 如果斷言失敗,程式終止執行,本質上斷言失敗會觸發一個異常型別:AssertionError

  • 斷言,主要用在預期結果和實際結果的比對

    height = int(input('輸入身高:'))
    print(height > 180)  # False
    assert  height > 180
    print("斷言有結果")
    

七、物件導向

(一)、類(Class)

  • 什麼是類:

    • 是指所有符合某種特徵的個體的集合
    • 類(Class) 是用來描述具有相同的屬性和方法的物件的集合。它定義了該集合中每個物件所共有的屬性和方法。
  • 類的表示:(下面三種寫法作用完全一樣)

    class 類名稱:
        # 類當中的內容
        屬性 ==》 特徵
        行為
    
        
    class 類名稱():
        pass
    
      
    class 類名稱(object):
        pass
    
    
    class Dog:
        # 類內容
        tailed = True
    
        def say(self):
            print('汪汪。。。')
    
  • 類的命名

    • 符合識別符號命名規則
    • 字母數字下劃線,不能是關鍵字,要有意義
    • 規範:大駝峰,SingleDog
  • 使用 類 的好處

    • 方便複用(如果你用函式寫,就要複製整塊程式碼,增加了程式碼量,增加了出錯率)
    • 方便擴充套件(函式寫段程式碼,若要升級、擴充套件,都十分複雜,容易出錯,用類來擴充套件,則方便清晰)
    • 方便維護(因為類是把抽象的東西對映成我們常見的,摸得到的東西,容易理解,維護也方便)

(二)、物件

  • 什麼是物件:

    • 物件指的是某個類當中的一個成員,一個個體
    • 物件是從類當中生成的, ==》 類是一個模型,是一個生產圖紙。
    • 物件就是類的具體例項
      • 類是函式的定義,物件是函式的呼叫
      • 例項、物件、object 都是同一個東西
    class Dog:
        # 類內容
        tailed = True
    
        def say(self):
            print('汪汪。。。')
            
    zhonghua = Dog() 
    print(zhonghua) # 是物件  <__main__.Dog object at 0x00000000022724A8>
    print(Dog) # 是類  <class '__main__.Dog'>
    
    # Dog 不加括號的時候是類
    zhonghua = Dog
    print(zhonghua) # <class '__main__.Dog'>
    

(三)、屬性和方法

  • 屬性就是指類或者物件的特徵。名詞
  • 方法就是指類或者物件的行為。動詞
  • 屬性:
    • 類屬性(類變數):類當中每一個成員都具備的特徵,類和物件都可以獲取類屬性
    • 例項屬性(例項變數)、物件屬性:類當中的成員不一定都具備的特徵,是物件獨有的,自己具備
  • 方法:
    • 類方法:每一個成員或者整個類都能呼叫的行為

    • 例項方法、物件方法:只能是需要一個單獨的成員呼叫的行為,不能是整個類呼叫

      • 不要用整個類去呼叫例項方法
      • 例項方法在定義的時候自帶一個引數:self,
      • 但是例項方法在呼叫的時候不需要傳 self 這個引數的實際引數
      class Dog:
          # 有尾巴
          # 類屬性
          tailed = True
      
          # 例項方法
          def say(self):
              print('汪汪汪。。。')
      
      # 物件
      teddy = Dog()
      
      # 類屬性的獲取
      print(Dog.tailed) # True
      
      # 物件獲取屬性
      print(teddy.tailed) # True
      
      # 屬性可以後天修改
      Dog.tailed = False
      print(Dog.tailed) # False
      print(teddy.tailed) # False
      
      teddy.tailed = '有時候有尾巴,有時候沒有'
      print(Dog.tailed) # False
      print(teddy.tailed) # 有時候有尾巴,有時候沒有
      
      
      # 類方法的呼叫
      # Dog.say() # 會報錯
      # Dog.say('abc') # 不要用整個類去呼叫例項方法
      # teddy.say('abc') # 會報錯
      teddy.say() # 汪汪汪。。。
      

(四)、物件的初始化

  • 一個物件:除了整個類都具備的屬性,還有自己的特徵。 物件自己的特徵就叫例項屬性或者物件屬性。

  • 每個物件都有自己不同的例項屬性,可以在物件生成的時候傳入實際引數,這個實際引數就是例項屬性,傳入實際引數時需要有對應的形式引數,這些形式引數不能在類後面直接定義,這裡就定義了一個特別函式,方法,_init_,在這裡面定義好的形式引數,最終在物件初始化的時候傳入實際引數,這個例項屬性產生的過程就叫物件的初始化。

  • 傳入的實際引數是在什麼時候呼叫的???

    teddy = Dog(name = 'teddy', color = 'blue') 自動呼叫 _init_
    不需要寫 Dog._init_()

    TODO: 一定不要寫成 _int_

    class Dog:
    
        tailed = True
    
        # 定義一個特別函式,方法,定義好的形式引數,最終在物件初始化的時候傳入實際引數
        def __init__(self, name, color):
            """初始化函式,初始化方法"""
            # 自定義物件產生的過程
            # 例項屬性的產生 self.name 定義一個叫做 name 的例項屬性
            self.name = name
            self.color = color
        def say(self):
            print('汪汪汪。。。')
    
    teddy = Dog(name = 'teddy', color = 'blue')
    teddy.say()
    
    # 獲取例項屬性
    print(teddy.color)
    
    # 類不能呼叫例項屬性
    # print(Dog.color)  # AttributeError: type object 'Dog' has no attribute 'color'
    

  • 例項化

    • 通過一個類去建立一個物件,就是例項化。

    • 例項化是產生物件的過程

    • 例項化就是函式的呼叫

    • 產生物件,例項化物件的時候,會自動呼叫 _init_ 這個方法

      self.name = name

      self.name ==> 例項屬性

      name ====> 引數, teddy 值。

      name 這個name是變數,和類和物件沒有關係

  • 什麼是 self :

    • 所謂的self,可以理解為自己,就是我們的例項本身,代表例項物件,誰去呼叫代表誰。

      Kitty 這個例項物件呼叫,self就代表Kitty

      jingel 這個例項物件去呼叫,self就代表jingel

    • 某個物件呼叫其方法時,python直譯器會把這個物件作為第一個引數傳遞給 self,只需要傳遞後面的引數即可

    • self 可以改成其他名字,但不建議改,你改了別人就不知道具體的含義了

    class Dog:
    
        tailed = True
    
        # 定義一個特別函式,方法,定義好的形式引數,最終在物件初始化的時候傳入實際引數
    
        def __init__(self, name, color='grey'):
            """初始化函式,初始化方法"""
            # 自定義物件產生的過程
            # 例項屬性的產生 self.name 定義一個叫做 name 的例項屬性
    
            # dog.name = name # 不能這樣寫,函式裡面不能使用全域性變數,這個時候 dog 這個物件還沒有產生出來
            # Dog.name = name # 也不能這麼寫,不能所有的狗都叫同一個名字
    
            self.name = name
            self.color = color
            print(self)
    
        def say(self):
            print('汪汪汪。。。')
    
    dog = Dog('teddy')
    print(dog.color)  # grey
    # dog
    print(dog) # self 和 dog 物件是同一個地址
    
    
    # ha = Dog('teddy')
    # print(ha.color)  # grey
    # # dog
    # print(ha) # self 和 ha 物件是同一個地址
    

(五)、例項方法、類方法、靜態方法

1、例項方法:

  • 定義:
    • 例項方法直接定義在類中
    • 第一個引數是 self (必須要寫),
  • 例項方法的訪問
    • 只有該類的例項物件都可以訪問,訪問例項方法的時候會自動將物件本身當成引數,傳給self接收
  • 在類和物件當中,例項方法是用的最多的。
  • 如果不知道該定義成例項方法,類方法還是靜態方法,就定義成例項方法
  • 呼叫方法:
    • obj.方法名()
    • 例項.方法()

2、類方法:

  • 定義:

    使用裝飾器 @classmethod。第一個引數必須是當前類物件,該引數名一般約定為“cls”,通過它來傳遞類的屬性和方法(不能傳例項的屬性和方法)

  • 呼叫:

    • 例項物件和類物件都可以呼叫
  • 應用場景:

    • 需要站在類的角度執行某個行為時,那麼就應該定義為類方法
  • 類方法呼叫

    • 類.類方法()

3、靜態方法:

  • 定義:

    • 使用裝飾器 @staticmethod 引數隨意,沒有 self 和 cls 引數,但是方法體中不能使用類或例項的任何屬性和方法
  • 呼叫:

    • 例項物件和類物件都可以呼叫。
  • 應用場景:

    • 存放邏輯程式碼,內部不需要引用類屬性和例項屬性
    • 當想在一個類當中定義一個方法,和這個類或者物件沒有直接的關係。
    • 你在方法當中,沒有使用到類或者是物件。
  • 靜態方法呼叫:

    • 類和物件,都可以呼叫靜態方法
  • 靜態方法存在的理由:

    • 放在類裡面方便管理

def say_static(times): # 放在這裡是普通的函式,和放在類裡面效果是一樣的,只是呼叫時這個直接呼叫,呼叫類裡面的需要加字首
    print(f'汪汪。。。{times} 聲')

class Dog:

    tailed = True

    # 定義一個特別函式,方法,定義好的形式引數,最終在物件初始化的時候傳入實際引數

    def __init__(self, name, color='grey'):
        """初始化函式,初始化方法"""
        self.name = name
        self.color = color
        print(self)

    # 例項方法
    def say(self, times):
        print(f'{self}汪汪汪。。。{times} 聲')

    # 靜態方法
    @staticmethod
    def say_static(times):
        print(f'汪汪汪。。。{times} 聲')
        

    # # 類方法。進化
    # def jinhua(self):
    #     print('狗類正在進化')
    #     Dog.tailed = False

    # 宣告:這是一個類方法
    # 固定寫法
    @classmethod
    def jinhua(cls):
        print('狗類正在進化')
        Dog.tailed = False


haha = Dog('haha')
yiyi = Dog('yiyi')
# print(haha.tailed) # F
# print(yiyi.tailed) # F

# Dog.jinhua() # jinhua()是例項方法,不能使用類去呼叫
# print(haha.tailed)
# print(yiyi.tailed)


# 類方法的呼叫
# Dog.jinhua()  # Dog 加括號表示物件,不加括號表示類
# haha.tailed


# haha.jinhua()
# print(haha.tailed)
#
# haha.say(5)


# 靜態方法的呼叫,類和物件,都可以呼叫靜態方法
haha.say_static(5)
Dog.say_static(6)

# 普通函式版
say_static(7)

(六)、繼承

(1)、類的繼承

  • 定義類兩種方式的區別:

    # Python2 中稱為經典類,在python3 中預設繼承 object
    class MyTest:
        pass
    
    # python2 中稱為新式類。
    class MyTest(object):
        pass
    # 注意點:python3 中上面兩種定義方法沒有區別,都是繼承 object 這個父類
    
  • 在python3 的繼承中,所有的類都預設繼承自 object 這個基類。

  • 子類通過繼承可以獲得父類的屬性和方法。

  • 被繼承的類叫父類(也叫基類),繼承的類叫子類

  • 注意:私有屬性不能繼承

  • 作用:

    • 子類通過繼承可以獲得父類的屬性和方法,提高開發的效率及程式碼的複用率
    # 普通寫法定義手機類和智慧手機類
    class Mobile:
        def __init__(self, model, color='blacd'):
            self.model = model
            self.color = color
    
        def call(self):
            """打電話"""
            print(f"{self} 手機正在打電話。")
    
    
    class SmartPhone:
        def __init__(self, model, color='blacd'):
            self.model = model
            self.color = color
    
        def call(self):
            """打電話"""
            print(f"{self} 手機正在打電話。")
    
        def play_game(self):
            print("玩遊戲")
    
    
    
    # 使用繼承
    class Mobile():
        def __init__(self, brand, model, color='blacd'):
            self.model = model
            self.color = color
            self.brand = brand
    
        def call(self):
            """打電話"""
            print(f"{self} 手機正在打電話。")
    
    
    class SmartPhone(Mobile):
    
        def play_game(self):
            print("玩遊戲")
    
    
    # iphone = SmartPhone()
    # iphone.play_game() # 這裡會報錯,初始化的時候需要呼叫__init__方法,自己沒有去找父類,父類的__init__需要傳引數
    
    iphone = SmartPhone('iphone12', 'apple')
    iphone.play_game()
    
    
    ​
    
    

(2)、超繼承

  • 重寫父類方法

    • 重寫,就是子類中,有一個和父類相同名字的方法,在子類中的方法會覆蓋掉父類中的同名方法
    • 如:同樣是打電話,第一版手機只能大語音電話,最新版手機可以打視訊電話
  • 呼叫重名的父類方法

    • 子類重寫了父類的方法之後,如何在子類中再呼叫父類的方法:
      • 方式一:父類名.方法名(self)
      • 方式二:super().方法名()
    class Mobile():
        def __init__(self, brand, model, color='blacd'):
            self.model = model
            self.color = color
            self.brand = brand
    
        def call(self):
            """打電話"""
            print(f"{self} 手機正在打電話。")
    
    
    class SmartPhone(Mobile):
        def __init__(self, model, brand, color='red', pixel = 2000):
            # self.model = model
            # self.color = color
            # self.brand = brand  # 這三行程式碼父類中有,可以使用 super()
            super().__init__(brand, model, color) # 使用 super() 直接呼叫父類的方法
            self.fiveG = True
            self.pixel = pixel
    
        def play_game(self):
            print("玩遊戲")
    
        def call(self):
            """智慧手機打電話"""
            print('開視訊')
            super().call()
    
    # super 函式的使用
    smart = SmartPhone('p40','huawei')
    print(smart.pixel)
    smart.call()
    
    
    

(七)、動態獲取屬性

  • 獲取物件屬性的時候,如果物件中沒有這個屬性,程式碼就會報錯

  • 可以使用 getattr( 物件, 屬性名稱 , 預設值) 動態獲取屬性,並在屬性後面傳入一個預設值,如果物件沒有這個屬性就會顯示預設值,程式碼就不會報錯

  • 還可以動態修改屬性,使用 setattr( 物件, 屬性名稱 , 屬性值)

    class Mobile:
    
        def __init__(self, brand, model):
            # 先天初始化過程中形成的屬性
            self.brand = brand
            self.model = model
    
        def call(self):
            print('正在打電話。。')
    
    iphone = Mobile('apple', 'xr')
    # 獲取屬性
    # print(iphone.brand)
    # 修改屬性
    # iphone.brand = 'aple'
    
    # 定義新的例項屬性
    # 後天養成的特性
    # iphone.video = '美顏'
    # print(iphone.video)
    
    # 獲取一個不存在的屬性
    # 如果獲取不存在的屬性,程式碼會報錯
    # print(iphone.games)  # AttributeError: 'Mobile' object has no attribute 'games'
    
    # 動態獲取屬性
    # getattr 內建函式
    
    # print(getattr(iphone, 'games')) # 還是報錯:AttributeError: 'Mobile' object has no attribute 'games'
    # default ,如果獲取不到屬性名,傳入 default 預設值,就不會報錯了
    # getattr 不會修改原來的物件的屬性
    print(getattr(iphone, 'games', '吃雞'))
    
    # print(iphone.games,) # 還是會報錯,因為iphone 沒有games屬性
    
    # 動態修改屬性
    setattr(iphone, 'games', '王者榮耀')
    print(iphone.games) # 王者榮耀
    

相關文章