主頁 > 後端開發 > Python基礎知識點六萬字總結,爆肝一周熬夜完成【建議收藏】

Python基礎知識點六萬字總結,爆肝一周熬夜完成【建議收藏】

2021-07-23 08:04:52 後端開發

大家好,我是辣條,

今天給大家帶來Python基礎知識點的總結,不夸張的說我一周才寫完,這才是第一彈,如果大家喜歡記得三連呦,我會火速更新下一彈,爭取把這個系列做完,希望得到大家的支持,

目錄

注釋

變數

輸出

輸入

轉換資料型別

運算子

條件陳述句

回圈

字串

串列

元組

字典

集合

公共操作

推導式

函式一

函式二

函式三

檔案操作

面向物件基礎

面向物件-繼承

面向物件-其他

例外

模塊和包


注釋

  • 注釋的分類

    • 單行: # 注釋內容,快捷鍵ctrl+/

    • 多行:""" 注釋內容 """''' 注釋內容 '''

  • 解釋器不執行注釋內容

注釋分為兩類:==單行注釋== 和 ==多行注釋==,

  • 單行注釋

只能注釋一行內容,語法如下:

# 注釋內容
  • 多行注釋

可以注釋多行內容,一般用在注釋一段代碼的情況, 語法如下:

"""
    第一行注釋
    第二行注釋
    第三行注釋
"""
?
'''
    注釋1
    注釋2
    注釋3
'''

快捷鍵: ==ctrl + /==

變數

變數就是一個存盤資料的的時候當前資料所在的記憶體地址的名字而已,

識別符號

識別符號命名規則是Python中定義各種名字的時候的統一規范,具體如下:

  • 由數字、字母、下劃線組成

  • 不能數字開頭

  • 不能使用內置關鍵字

  • 嚴格區分大小寫

命名習慣

  • 見名知義,

  • 大駝峰:即每個單詞首字母都大寫,例如:MyName

  • 小駝峰:第二個(含)以后的單詞首字母大寫,例如:myName

  • 下劃線:例如:my_name

認識資料型別

檢測資料型別的方法:type()

a = 1
print(type(a))  # <class 'int'> -- 整型
?
b = 1.1
print(type(b))  # <class 'float'> -- 浮點型
?
c = True
print(type(c))  # <class 'bool'> -- 布爾型
?
d = '12345'
print(type(d))  # <class 'str'> -- 字串
?
e = [10, 20, 30]
print(type(e))  # <class 'list'> -- 串列
?
f = (10, 20, 30)
print(type(f))  # <class 'tuple'> -- 元組
?
h = {10, 20, 30}
print(type(h))  # <class 'set'> -- 集合
?
g = {'name': 'TOM', 'age': 20}
print(type(g))  # <class 'dict'> -- 字典

輸出

作用:程式輸出內容給用戶

print('hello Python')
?
age = 19
print(age)
?
# 需求:輸出“今年我的年齡是19歲”

格式化符號

格式符號轉換
==%s==字串
==%d==有符號的十進制整數
==%f==浮點數
%c字符
%u無符號十進制整數
%o八進制整數
%x十六進制整數(小寫ox)
%X十六進制整數(大寫OX)
%e科學計數法(小寫'e')
%E科學計數法(大寫'E')
%g%f和%e的簡寫
%G%f和%E的簡寫

轉義字符

  • \n:換行,

  • \t:制表符,一個tab鍵(4個空格)的距離,

結束符

print('輸出的內容', end="\n")

在Python中,print(), 默認自帶end="\n"這個換行結束符,所以導致每兩個print直接會換行展示,用戶可以按需求更改結束符,

輸入

在Python中,程式接收用戶輸入的資料的功能即是輸入,

input("提示資訊")

輸入的特點

  • 當程式執行到input,等待用戶輸入,輸入完成之后才繼續向下執行,

  • 在Python中,input接收用戶輸入后,一般存盤到變數,方便使用,

  • 在Python中,input會把接收到的任意用戶輸入的資料都當做字串處理,

轉換資料型別

函式說明
==int(x [,base ])==將x轉換為一個整數
==float(x )==將x轉換為一個浮點數
complex(real [,imag ])創建一個復數,real為實部,imag為虛部
==str(x )==將物件 x 轉換為字串
repr(x )將物件 x 轉換為運算式字串
==eval(str )==用來計算在字串中的有效Python運算式,并回傳一個物件
==tuple(s )==將序列 s 轉換為一個元組
==list(s )==將序列 s 轉換為一個串列
chr(x )將一個整數轉換為一個Unicode字符
ord(x )將一個字符轉換為它的ASCII整數值
hex(x )將一個整數轉換為一個十六進制字串
oct(x )將一個整數轉換為一個八進制字串
bin(x )

將一個整數轉換為一個二進制字串

轉換資料型別常用的函式

  • int()

  • float()

  • str()

  • list()

  • tuple()

  • eval()

運算子

算數運算子

運算子描述實體
+1 + 1 輸出結果為 2
-1-1 輸出結果為 0
*2 * 2 輸出結果為 4
/10 / 2 輸出結果為 5
//整除9 // 4 輸出結果為2
%取余9 % 4 輸出結果為 1
**指數2 ** 4 輸出結果為 16,即 2 * 2 * 2 * 2
()小括號小括號用來提高運算優先級,即 (1 + 2) * 3 輸出結果為 9

賦值運算子

運算子描述實體
=賦值=右側的結果賦值給等號左側的變數

復合賦值運算子

運算子描述實體
+=加法賦值運算子c += a 等價于 c = c + a
-=減法賦值運算子c -= a 等價于 c = c- a
*=乘法賦值運算子c *= a 等價于 c = c * a
/=除法賦值運算子c /= a 等價于 c = c / a
//=整除賦值運算子c //= a 等價于 c = c // a
%=取余賦值運算子c %= a 等價于 c = c % a
**=冪賦值運算子c ** = a 等價于 c = c ** a

比較運算子

運算子描述實體
==判斷相等,如果兩個運算元的結果相等,則條件結果為真(True),否則條件結果為假(False)如a=3,b=3,則(a == b) 為 True
!=不等于 ,如果兩個運算元的結果不相等,則條件為真(True),否則條件結果為假(False)如a=3,b=3,則(a == b) 為 True如a=1,b=3,則(a != b) 為 True
>運算子左側運算元結果是否大于右側運算元結果,如果大于,則條件為真,否則為假如a=7,b=3,則(a > b) 為 True
<運算子左側運算元結果是否小于右側運算元結果,如果小于,則條件為真,否則為假如a=7,b=3,則(a < b) 為 False
>=運算子左側運算元結果是否大于等于右側運算元結果,如果大于,則條件為真,否則為假如a=7,b=3,則(a < b) 為 False如a=3,b=3,則(a >= b) 為 True
<=運算子左側運算元結果是否小于等于右側運算元結果,如果小于,則條件為真,否則為假如a=3,b=3,則(a <= b) 為 True

邏輯運算子

運算子邏輯運算式描述實體
andx and y布爾"與":如果 x 為 False,x and y 回傳 False,否則它回傳 y 的值,True and False, 回傳 False,
orx or y布爾"或":如果 x 是 True,它回傳 True,否則它回傳 y 的值,False or True, 回傳 True,
notnot x布爾"非":如果 x 為 True,回傳 False ,如果 x 為 False,它回傳 True,not True 回傳 False, not False 回傳 True

條件陳述句

假設一個場景:

其實這里所謂的判斷就是條件陳述句,即條件成立執行某些代碼,條件不成立則不執行這些代碼

語法

if 條件:
    條件成立執行的代碼1
    條件成立執行的代碼2
    ......

if...else...

作用:條件成立執行if下方的代碼; 條件不成立執行else下方的代碼,

if 條件:
    條件成立執行的代碼1
    條件成立執行的代碼2
    ......
else:
    條件不成立執行的代碼1
    條件不成立執行的代碼2
    ......

實體:工齡判斷

age = int(input('請輸入您的年齡:'))
if age < 18:
    print(f'您的年齡是{age},童工一枚')
elif (age >= 18) and (age <= 60):
    print(f'您的年齡是{age},合法工齡')
elif age > 60:
    print(f'您的年齡是{age},可以退休')

拓展:age >= 18 and age <= 60可以化簡為18 <= age <= 60

if嵌套

if 條件1:
    條件1成立執行的代碼
    條件1成立執行的代碼
    
    if 條件2:
        條件2成立執行的代碼
        條件2成立執行的代碼
   

應用:猜拳游戲

需求分析:

  • 參與游戲的角色

    • 玩家

      • 手動出拳

    • 電腦

      • 隨機出拳

  • 判斷輸贏

    • 玩家獲勝

    玩家電腦
    石頭剪刀
    剪刀
    石頭
    • 平局

      • 玩家出拳 和 電腦出拳相同

    • 電腦獲勝

隨機做法:

  1. 匯出random模塊

  2. random.randint(開始,結束)

"""
提示:0-石頭,1-剪刀,2-布
1. 出拳
玩家輸入出拳
電腦隨機出拳
?
2. 判斷輸贏
玩家獲勝
平局
電腦獲勝
"""
?
# 匯入random模塊
import random
?
# 計算電腦出拳的亂數字
computer = random.randint(0, 2)
print(computer)
?
player = int(input('請出拳:0-石頭,1-剪刀,2-布:'))
?
# 玩家勝利 p0:c1 或 p1:c2 或 p2:c0
if (player == 0 and computer == 1) or (player == 1 and computer == 2) or (player == 2 and computer == 0):
    print('玩家獲勝')
?
# 平局:玩家 == 電腦
elif player == computer:
    print('平局')
else:
    print('電腦獲勝')

三目運算子

三目運算子也叫三元運算子,

語法如下:

值1 if 條件 else 值2

快速體驗:

a = 1
b = 2
?
c = a if a > b else b
print(c)

回圈

回圈的作用:讓代碼更高效的重復執行,

回圈的分類

在Python中,回圈分為whilefor兩種,最終實作效果相同,

while的語法

while 條件:
    條件成立重復執行的代碼1
    條件成立重復執行的代碼2
    ......

while的應用

計算1-100累加和

分析:1-100的累加和,即1 + 2 + 3 + 4 +….,即前兩個數字的相加結果 + 下一個數字( 前一個數字 + 1),

i = 1
result = 0
while i <= 100:
    result += i
    i += 1
?
# 輸出5050
print(result)

注意:為了驗證程式的準確性,可以先改小數值,驗證結果正確后,再改成1-100做累加,

計算1-100偶數累加和

分析:1-100的偶數和,即 2 + 4 + 6 + 8....,得到偶數的方法如下:

  • 偶數即是和2取余結果為0的數字,可以加入條件陳述句判斷是否為偶數,為偶數則累加

  • 初始值為0 / 2 , 計數器每次累加2

方法一:條件判斷和2取余數則累加

# 方法一:條件判斷和2取余數為0則累加計算
i = 1
result = 0
while i <= 100:
    if i % 2 == 0:
        result += i
    i += 1
?
# 輸出2550
print(result)

方法二:計數器控制

# 方法二:計數器控制增量為2
i = 0
result = 0
while i <= 100:
    result += i
    i += 2
?
# 輸出2550
print(result)

while回圈嵌套

故事梗概:有天女朋友又生氣了,懲罰:說3遍“媳婦兒, 我錯了”,這個程式是不是回圈即可?但如果女朋友說:還要刷今天晚飯的碗,這個程式怎么書寫?

while 條件:
    print('媳婦兒, 我錯了')
print('刷晚飯的碗')

但如果女朋友還是生氣,把這套懲罰要連續3天都執行,有如何書寫程式?

while 條件:
    while 條件:
        print('媳婦兒, 我錯了')
    print('刷晚飯的碗')

while 條件1:
    條件1成立執行的代碼
    ......
    while 條件2:
        條件2成立執行的代碼
        ......

總結:所謂while回圈嵌套,就是一個while里面嵌套一個while的寫法,每個while和之前的基礎語法是相同的,

for回圈

語法

for 臨時變數 in 序列:
    重復執行的代碼1
    重復執行的代碼2
    ......

else

回圈可以和else配合使用,else下方縮進的代碼指的是==當回圈正常結束之后要執行的代碼==,

while...else

需求:女朋友生氣了,要懲罰:連續說5遍“媳婦兒,我錯了”,如果道歉正常完畢女朋友就原諒我了,這個程式怎么寫?

i = 1
while i <= 5:
    print('媳婦兒,我錯了')
    i += 1
print('媳婦兒原諒我了...')

思考: 這個print是不是沒有回圈也能執行?

語法

while 條件:
    條件成立重復執行的代碼
else:
    回圈正常結束之后要執行的代碼

示例

i = 1
while i <= 5:
    print('媳婦兒,我錯了')
    i += 1
else:
    print('媳婦原諒我了,真開心,哈哈哈哈')

for...else

語法

for 臨時變數 in 序列:
    重復執行的代碼
    ...
else:
    回圈正常結束之后要執行的代碼

所謂else指的是回圈正常結束之后要執行的代碼,即如果是break終止回圈的情況,else下方縮進的代碼將不執行,

示例

str1 = 'itheima'
for i in str1:
    print(i)
else:
    print('回圈正常結束之后執行的代碼')

總結

  • 回圈的作用:控制代碼重復執行

  • while語法

while 條件:
    條件成立重復執行的代碼1
    條件成立重復執行的代碼2
    ......
  • while回圈嵌套語法

while 條件1:
    條件1成立執行的代碼
    ......
    while 條件2:
        條件2成立執行的代碼
        ......
  • for回圈語法

for 臨時變數 in 序列:
    重復執行的代碼1
    重復執行的代碼2
    ......
  • break退出整個回圈

  • continue退出本次回圈,繼續執行下一次重復執行的代碼

  • else

    • while和for都可以配合else使用

    • else下方縮進的代碼含義:當回圈正常結束后執行的代碼

    • break終止回圈不會執行else下方縮進的代碼

    • continue退出回圈的方式執行else下方縮進的代碼

字串

字串是 Python 中最常用的資料型別,我們一般使用引號來創建字串,創建字串很簡單,只要為變數分配一個值即可,

a = 'hello world'
b = "abcdefg"
print(type(a))
print(type(b))

注意:控制臺顯示結果為<class 'str'>, 即資料型別為str(字串),

字串輸出

print('hello world')
?
name = 'Tom'
print('我的名字是%s' % name)
print(f'我的名字是{name}')

字串輸入

在Python中,使用input()接收用戶輸入,

  • 代碼

name = input('請輸入您的名字:')
print(f'您輸入的名字是{name}')
print(type(name))
?
password = input('請輸入您的密碼:')
print(f'您輸入的密碼是{password}')
print(type(password))

切片

切片是指對操作的物件截取其中一部分的操作,字串、串列、元組都支持切片操作,

語法

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

注意

  1. 不包含結束位置下標對應的資料, 正負整數均可;

  2. 步長是選取間隔,正負整數均可,默認步長為1,

體驗

name = "abcdefg"
?
print(name[2:5:1])  # cde
print(name[2:5])  # cde
print(name[:5])  # abcde
print(name[1:])  # bcdefg
print(name[:])  # abcdefg
print(name[::2])  # aceg
print(name[:-1])  # abcdef, 負1表示倒數第一個資料
print(name[-4:-1])  # def
print(name[::-1])  # gfedcba

修改

所謂修改字串,指的就是通過函式的形式修改字串中的資料,

  • replace():替換

  1. 語法

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

注意:替換次數如果查出子串出現次數,則替換次數為該子串出現次數,

  1. 快速體驗

mystr = "hello world and itcast and itheima and Python"
?
# 結果:hello world he itcast he itheima he Python
print(mystr.replace('and', 'he'))
# 結果:hello world he itcast he itheima he Python
print(mystr.replace('and', 'he', 10))
# 結果:hello world and itcast and itheima and Python
print(mystr)

注意:資料按照是否能直接修改分為==可變型別==和==不可變型別==兩種,字串型別的資料修改的時候不能改變原有字串,屬于不能直接修改資料的型別即是不可變型別,

  • split():按照指定字符分割字串,

  1. 語法

字串序列.split(分割字符, num)

注意:num表示的是分割字符出現的次數,即將來回傳資料個數為num+1個,

  1. 快速體驗

mystr = "hello world and itcast and itheima and Python"
?
# 結果:['hello world ', ' itcast ', ' itheima ', ' Python']
print(mystr.split('and'))
# 結果:['hello world ', ' itcast ', ' itheima and Python']
print(mystr.split('and', 2))
# 結果:['hello', 'world', 'and', 'itcast', 'and', 'itheima', 'and', 'Python']
print(mystr.split(' '))
# 結果:['hello', 'world', 'and itcast and itheima and Python']
print(mystr.split(' ', 2))

注意:如果分割字符是原有字串中的子串,分割后則丟失該子串,

  • join():用一個字符或子串合并字串,即是將多個字串合并為一個新的字串,

  1. 語法

字符或子串.join(多字串組成的序列)
  1. 快速體驗

list1 = ['chuan', 'zhi', 'bo', 'ke']
t1 = ('aa', 'b', 'cc', 'ddd')
# 結果:chuan_zhi_bo_ke
print('_'.join(list1))
# 結果:aa...b...cc...ddd
print('...'.join(t1))

  • capitalize():將字串第一個字符轉換成大寫,

mystr = "hello world and itcast and itheima and Python"
?
# 結果:Hello world and itcast and itheima and python
print(mystr.capitalize())

注意:capitalize()函式轉換后,只字串第一個字符大寫,其他的字符全都小寫,

  • title():將字串每個單詞首字母轉換成大寫,

mystr = "hello world and itcast and itheima and Python"
?
# 結果:Hello World And Itcast And Itheima And Python
print(mystr.title())

  • lower():將字串中大寫轉小寫,

mystr = "hello world and itcast and itheima and Python"
?
# 結果:hello world and itcast and itheima and python
print(mystr.lower())

  • upper():將字串中小寫轉大寫,

mystr = "hello world and itcast and itheima and Python"
?
# 結果:HELLO WORLD AND ITCAST AND ITHEIMA AND PYTHON
print(mystr.upper())

判斷

所謂判斷即是判斷真偽,回傳的結果是布爾型資料型別:True 或 False,

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

  1. 語法

字串序列.startswith(子串, 開始位置下標, 結束位置下標)
  1. 快速體驗

mystr = "hello world and itcast and itheima and Python   "
?
# 結果:True
print(mystr.startswith('hello'))
?
# 結果False
print(mystr.startswith('hello', 5, 20))

  • endswith()::檢查字串是否是以指定子串結尾,是則回傳 True,否則回傳 False,如果設定開始和結束位置下標,則在指定范圍內檢查,

  1. 語法

字串序列.endswith(子串, 開始位置下標, 結束位置下標)
  1. 快速體驗

mystr = "hello world and itcast and itheima and Python"
?
# 結果:True
print(mystr.endswith('Python'))
?
# 結果:False
print(mystr.endswith('python'))
?
# 結果:False
print(mystr.endswith('Python', 2, 20))

  • isalpha():如果字串至少有一個字符并且所有字符都是字母則回傳 True, 否則回傳 False,

mystr1 = 'hello'
mystr2 = 'hello12345'
?
# 結果:True
print(mystr1.isalpha())
?
# 結果:False
print(mystr2.isalpha())

  • isdigit():如果字串只包含數字則回傳 True 否則回傳 False,

mystr1 = 'aaa12345'
mystr2 = '12345'
?
# 結果: False
print(mystr1.isdigit())
?
# 結果:False
print(mystr2.isdigit())

  • isalnum():如果字串至少有一個字符并且所有字符都是字母或數字則返 回 True,否則回傳 False,

mystr1 = 'aaa12345'
mystr2 = '12345-'
?
# 結果:True
print(mystr1.isalnum())
?
# 結果:False
print(mystr2.isalnum())

  • isspace():如果字串中只包含空白,則回傳 True,否則回傳 False,

mystr1 = '1 2 3 4 5'
mystr2 = '     '
?
# 結果:False
print(mystr1.isspace())
?
# 結果:True
print(mystr2.isspace())

總結

  • 下標

    • 計算機為資料序列中每個元素分配的從0開始的編號

  • 切片

序列名[開始位置下標:結束位置下標:步長]
  • 常用操作方法

    • find()

    • index()

串列

思考:有一個人的姓名(TOM)怎么書寫存盤程式?

答:變數,

思考:如果一個班級100位學生,每個人的姓名都要存盤,應該如何書寫程式?宣告100個變數嗎?

答:串列即可, 串列一次性可以存盤多個資料,

串列的格式

[資料1, 資料2, 資料3, 資料4......]

串列可以一次性存盤多個資料,且可以為不同資料型別,

串列的常用操作

串列的作用是一次性存盤多個資料,程式員可以對這些資料進行的操作有:增、刪、改、查,

查找

下標

name_list = ['Tom', 'Lily', 'Rose']
?
print(name_list[0])  # Tom
print(name_list[1])  # Lily
print(name_list[2])  # Rose

函式

  • index():回傳指定資料所在位置的下標 ,

  1. 語法

串列序列.index(資料, 開始位置下標, 結束位置下標)
  1. 快速體驗

name_list = ['Tom', 'Lily', 'Rose']
?
print(name_list.index('Lily', 0, 2))  # 1

注意:如果查找的資料不存在則報錯,

  • count():統計指定資料在當前串列中出現的次數,

name_list = ['Tom', 'Lily', 'Rose']
?
print(name_list.count('Lily'))  # 1
  • len():訪問串列長度,即串列中資料的個數,

name_list = ['Tom', 'Lily', 'Rose']
?
print(len(name_list))  # 3

判斷是否存在

  • in:判斷指定資料在某個串列序列,如果在回傳True,否則回傳False

name_list = ['Tom', 'Lily', 'Rose']
?
# 結果:True
print('Lily' in name_list)
?
# 結果:False
print('Lilys' in name_list)

  • not in:判斷指定資料不在某個串列序列,如果不在回傳True,否則回傳False

name_list = ['Tom', 'Lily', 'Rose']
?
# 結果:False
print('Lily' not in name_list)
?
# 結果:True
print('Lilys' not in name_list)
  • 體驗案例

需求:查找用戶輸入的名字是否已經存在,

name_list = ['Tom', 'Lily', 'Rose']
?
name = input('請輸入您要搜索的名字:')
?
if name in name_list:
    print(f'您輸入的名字是{name}, 名字已經存在')
else:
    print(f'您輸入的名字是{name}, 名字不存在')

增加

作用:增加指定資料到串列中,

  • append():串列結尾追加資料,

  1. 語法

串列序列.append(資料)
  1. 體驗

name_list = ['Tom', 'Lily', 'Rose']
?
name_list.append('xiaoming')
?
# 結果:['Tom', 'Lily', 'Rose', 'xiaoming']
print(name_list)

串列追加資料的時候,直接在原串列里面追加了指定資料,即修改了原串列,故串列為可變型別資料,

  1. 注意點

如果append()追加的資料是一個序列,則追加整個序列到串列

name_list = ['Tom', 'Lily', 'Rose']
?
name_list.append(['xiaoming', 'xiaohong'])
?
# 結果:['Tom', 'Lily', 'Rose', ['xiaoming', 'xiaohong']]
print(name_list)

  • extend():串列結尾追加資料,如果資料是一個序列,則將這個序列的資料逐一添加到串列,

  1. 語法

串列序列.extend(資料)
  1. 快速體驗

    2.1 單個資料

name_list = ['Tom', 'Lily', 'Rose']
?
name_list.extend('xiaoming')
?
# 結果:['Tom', 'Lily', 'Rose', 'x', 'i', 'a', 'o', 'm', 'i', 'n', 'g']
print(name_list)

2.2 序列資料

name_list = ['Tom', 'Lily', 'Rose']
?
name_list.extend(['xiaoming', 'xiaohong'])
?
# 結果:['Tom', 'Lily', 'Rose', 'xiaoming', 'xiaohong']
print(name_list)

  • insert():指定位置新增資料,

  1. 語法

串列序列.insert(位置下標, 資料)
  1. 快速體驗

name_list = ['Tom', 'Lily', 'Rose']
?
name_list.insert(1, 'xiaoming')
?
# 結果:['Tom', 'xiaoming', 'Lily', 'Rose']
print(name_list)

洗掉

  • del

  • 語法

del 目標

快速體驗

洗掉串列

name_list = ['Tom', 'Lily', 'Rose']
?
# 結果:報錯提示:name 'name_list' is not defined
del name_list
print(name_list)

洗掉指定資料

name_list = ['Tom', 'Lily', 'Rose']
?
del name_list[0]
?
# 結果:['Lily', 'Rose']
print(name_list)

  • pop():洗掉指定下標的資料(默認為最后一個),并回傳該資料,

  • 語法

串列序列.pop(下標)
  1. 快速體驗

name_list = ['Tom', 'Lily', 'Rose']
?
del_name = name_list.pop(1)
?
# 結果:Lily
print(del_name)
?
# 結果:['Tom', 'Rose']
print(name_list)

  • remove():移除串列中某個資料的第一個匹配項,

  1. 語法

串列序列.remove(資料)
  1. 快速體驗

name_list = ['Tom', 'Lily', 'Rose']
?
name_list.remove('Rose')
?
# 結果:['Tom', 'Lily']
print(name_list)

  • clear():清空串列

name_list = ['Tom', 'Lily', 'Rose']
?
name_list.clear()
print(name_list) # 結果: []

修改

  • 修改指定下標資料

name_list = ['Tom', 'Lily', 'Rose']
?
name_list[0] = 'aaa'
?
# 結果:['aaa', 'Lily', 'Rose']
print(name_list)

  • 逆置:reverse()

num_list = [1, 5, 2, 3, 6, 8]
?
num_list.reverse()
?
# 結果:[8, 6, 3, 2, 5, 1]
print(num_list)

  • 排序:sort()

  1. 語法

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

注意:reverse表示排序規則,reverse = True 降序, reverse = False 升序(默認)

  1. 快速體驗

num_list = [1, 5, 2, 3, 6, 8]
?
num_list.sort()
?
# 結果:[1, 2, 3, 5, 6, 8]
print(num_list)

復制

函式:copy()

name_list = ['Tom', 'Lily', 'Rose']
?
name_li2 = name_list.copy()
?
# 結果:['Tom', 'Lily', 'Rose']
print(name_li2)

串列嵌套

所謂串列嵌套指的就是一個串列里面包含了其他的子串列,

應用場景:要存盤班級一、二、三三個班級學生姓名,且每個班級的學生姓名在一個串列,

name_list = [['小明', '小紅', '小綠'], ['Tom', 'Lily', 'Rose'], ['張三', '李四', '王五']]

思考: 如何查找到資料"李四"?

# 第一步:按下標查找到李四所在的串列
print(name_list[2])
?
# 第二步:從李四所在的串列里面,再按下標找到資料李四
print(name_list[2][1])

總結

  • 串列的格式

[資料1, 資料2, 資料3]
  • 常用操作方法

    • index()

    • len()

    • append()

    • pop()

    • remove()

  • 串列嵌套

name_list = [['小明', '小紅', '小綠'], ['Tom', 'Lily', 'Rose'], ['張三', '李四', '王五']]
name_list[2][1]

元組

思考:如果想要存盤多個資料,但是這些資料是不能修改的資料,怎么做?

答:串列?串列可以一次性存盤多個資料,但是串列中的資料允許更改,

num_list = [10, 20, 30]
num_list[0] = 100

==一個元組可以存盤多個資料,元組內的資料是不能修改的,==

定義元組

元組特點:定義元組使用==小括號==,且==逗號==隔開各個資料,資料可以是不同的資料型別,

# 多個資料元組
t1 = (10, 20, 30)
?
# 單個資料元組
t2 = (10,)

注意:如果定義的元組只有一個資料,那么這個資料后面也好添加逗號,否則資料型別為唯一的這個資料的資料型別

t2 = (10,)
print(type(t2))  # tuple
?
t3 = (20)
print(type(t3))  # int
?
t4 = ('hello')
print(type(t4))  # str

元組的常見操作

元組資料不支持修改,只支持查找,具體如下:

  • 按下標查找資料

tuple1 = ('aa', 'bb', 'cc', 'bb')
print(tuple1[0])  # aa

  • index():查找某個資料,如果資料存在回傳對應的下標,否則報錯,語法和串列、字串的index方法相同,

tuple1 = ('aa', 'bb', 'cc', 'bb')
print(tuple1.index('aa'))  # 0

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

tuple1 = ('aa', 'bb', 'cc', 'bb')
print(tuple1.count('bb'))  # 2

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

tuple1 = ('aa', 'bb', 'cc', 'bb')
print(len(tuple1))  # 4

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

tuple1 = ('aa', 'bb', 'cc', 'bb')
tuple1[0] = 'aaa'

但是如果元組里面有串列,修改串列里面的資料則是支持的,故自覺很重要,

tuple2 = (10, 20, ['aa', 'bb', 'cc'], 50, 30)
print(tuple2[2])  # 訪問到串列
?
# 結果:(10, 20, ['aaaaa', 'bb', 'cc'], 50, 30)
tuple2[2][0] = 'aaaaa'
print(tuple2)

總結

  • 定義元組

t1 = (10, 20, 30)
?
t2 = (10,)
  • 常用操作方法

    • index()

    • len()

字典

思考1: 如果有多個資料,例如:'Tom', '男', 20,如何快速存盤?

答:串列

list1 = ['Tom', '男', 20]

思考2:如何查找到資料'Tom'?

答:查找到下標為0的資料即可,

list1[0]

思考3:如果將來資料順序發生變化,如下所示,還能用list1[0]訪問到資料'Tom'嗎?,

list1 = ['男', 20, 'Tom']

答:不能,資料'Tom'此時下標為2,

思考4:資料順序發生變化,每個資料的下標也會隨之變化,如何保證資料順序變化前后能使用同一的標準查找資料呢?

答:字典,字典里面的資料是以==鍵值對==形式出現,字典資料和資料順序沒有關系,即字典不支持下標,后期無論資料如何變化,只需要按照對應的鍵的名字查找資料即可,

創建字典的語法

字典特點:

  • 符號為==大括號==

  • 資料為==鍵值對==形式出現

  • 各個鍵值對之間用==逗號==隔開

# 有資料字典
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
?
# 空字典
dict2 = {}
?
dict3 = dict()

注意:一般稱冒號前面的為鍵(key),簡稱k;冒號后面的為值(value),簡稱v,

字典常見操作

寫法:==字典序列[key] = 值==

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

dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
?
dict1['name'] = 'Rose'
# 結果:{'name': 'Rose', 'age': 20, 'gender': '男'}
print(dict1)
?
dict1['id'] = 110
?
# {'name': 'Rose', 'age': 20, 'gender': '男', 'id': 110}
print(dict1)

注意:字典為可變型別,

  • del() / del:洗掉字典或洗掉字典中指定鍵值對,

dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
?
del dict1['gender']
# 結果:{'name': 'Tom', 'age': 20}
print(dict1)

  • clear():清空字典

dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
?
dict1.clear()
print(dict1)  # {}

寫法:==字典序列[key] = 值==

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

值查找

dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
print(dict1['name'])  # Tom
print(dict1['id'])  # 報錯

如果當前查找的key存在,則回傳對應的值;否則則報錯,

get()

  • 語法

字典序列.get(key, 默認值)

注意:如果當前查找的key不存在則回傳第二個引數(默認值),如果省略第二個引數,則回傳None,

  • 快速體驗

dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
print(dict1.get('name'))  # Tom
print(dict1.get('id', 110))  # 110
print(dict1.get('id'))  # None

keys()

dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
print(dict1.keys())  # dict_keys(['name', 'age', 'gender'])

values()

dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
print(dict1.values())  # dict_values(['Tom', 20, '男'])

items()

dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
print(dict1.items())  # dict_items([('name', 'Tom'), ('age', 20), ('gender', '男')])

總結

  • 定義字典

dict1 = {'name': 'Python', 'age': 30}
?
dict2 = {}
?
dict3 = dict()
  • 常見操作

    • 增/改

字典序列[key] = 值
  • 查找

    • 字典序列[key]

    • keys()

    • values()

    • items()

集合

創建集合

創建集合使用{}set(), 但是如果要創建空集合只能使用set(),因為{}用來創建空字典,

s1 = {10, 20, 30, 40, 50}
print(s1)
?
s2 = {10, 30, 20, 10, 30, 40, 30, 50}
print(s2)
?
s3 = set('abcdefg')
print(s3)
?
s4 = set()
print(type(s4))  # set
?
s5 = {}
print(type(s5))  # dict

特點:

  1. 集合可以去掉重復資料;

  2. 集合資料是無序的,故不支持下標

集合常見操作方法

增加資料

  • add()

s1 = {10, 20}
s1.add(100)
s1.add(10)
print(s1)  # {100, 10, 20}

因為集合有去重功能,所以,當向集合內追加的資料是當前集合已有資料的話,則不進行任何操作,

  • update(), 追加的資料是序列,

s1 = {10, 20}
# s1.update(100)  # 報錯
s1.update([100, 200])
s1.update('abc')
print(s1)

洗掉資料

  • remove(),洗掉集合中的指定資料,如果資料不存在則報錯,

s1 = {10, 20}
?
s1.remove(10)
print(s1)
?
s1.remove(10)  # 報錯
print(s1)

  • discard(),洗掉集合中的指定資料,如果資料不存在也不會報錯,

s1 = {10, 20}
?
s1.discard(10)
print(s1)
?
s1.discard(10)
print(s1)

  • pop(),隨機洗掉集合中的某個資料,并回傳這個資料,

s1 = {10, 20, 30, 40, 50}
?
del_num = s1.pop()
print(del_num)
print(s1)

查找資料

  • in:判斷資料在集合序列

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

s1 = {10, 20, 30, 40, 50}
?
print(10 in s1)
print(10 not in s1)

總結

  • 創建集合

    • 有資料集合

    s1 = {資料1, 資料2, ...}
    • 無資料集合

    s1 = set()
  • 常見操作

    • 增加資料

      • add()

      • update()

    • 洗掉資料

      • remove()

      • discard()

公共操作

運算子

運算子描述支持的容器型別
+合并字串、串列、元組
*復制字串、串列、元組
in元素是否存在字串、串列、元組、字典
not in元素是否不存在字串、串列、元組、字典

+

# 1. 字串 
str1 = 'aa'
str2 = 'bb'
str3 = str1 + str2
print(str3)  # aabb
?
?
# 2. 串列 
list1 = [1, 2]
list2 = [10, 20]
list3 = list1 + list2
print(list3)  # [1, 2, 10, 20]
?
# 3. 元組 
t1 = (1, 2)
t2 = (10, 20)
t3 = t1 + t2
print(t3)  # (10, 20, 100, 200)

*

# 1. 字串
print('-' * 10)  # ----------
?
# 2. 串列
list1 = ['hello']
print(list1 * 4)  # ['hello', 'hello', 'hello', 'hello']
?
# 3. 元組
t1 = ('world',)
print(t1 * 4)  # ('world', 'world', 'world', 'world')

in或not in

# 1. 字串
print('a' in 'abcd')  # True
print('a' not in 'abcd')  # False
?
# 2. 串列
list1 = ['a', 'b', 'c', 'd']
print('a' in list1)  # True
print('a' not in list1)  # False
?
# 3. 元組
t1 = ('a', 'b', 'c', 'd')
print('aa' in t1)  # False
print('aa' not in t1)  # True

公共方法

函式描述
len()計算容器中元素個數
del 或 del()洗掉
max()回傳容器中元素最大值
min()回傳容器中元素最小值
range(start, end, step)生成從start到end的數字,步長為 step,供for回圈使用
enumerate()函式用于將一個可遍歷的資料物件(如串列、元組或字串)組合為一個索引序列,同時列出資料和資料下標,一般用在 for 回圈當中,

len()

# 1. 字串
str1 = 'abcdefg'
print(len(str1))  # 7
?
# 2. 串列
list1 = [10, 20, 30, 40]
print(len(list1))  # 4
?
# 3. 元組
t1 = (10, 20, 30, 40, 50)
print(len(t1))  # 5
?
# 4. 集合
s1 = {10, 20, 30}
print(len(s1))  # 3
?
# 5. 字典
dict1 = {'name': 'Rose', 'age': 18}
print(len(dict1))  # 2

del()

# 1. 字串
str1 = 'abcdefg'
del str1
print(str1)
?
# 2. 串列
list1 = [10, 20, 30, 40]
del(list1[0])
print(list1)  # [20, 30, 40]

max()

# 1. 字串
str1 = 'abcdefg'
print(max(str1))  # g
?
# 2. 串列
list1 = [10, 20, 30, 40]
print(max(list1))  # 40

min()

# 1. 字串
str1 = 'abcdefg'
print(min(str1))  # a
?
# 2. 串列
list1 = [10, 20, 30, 40]
print(min(list1))  # 10

range()

# 1 2 3 4 5 6 7 8 9
for i in range(1, 10, 1):
    print(i)
?
# 1 3 5 7 9
for i in range(1, 10, 2):
    print(i)
?
# 0 1 2 3 4 5 6 7 8 9
for i in range(10):
    print(i)

注意:range()生成的序列不包含end數字,

enumerate()

  • 語法

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

注意:start引數用來設定遍歷資料的下標的起始值,默認為0,

  • 快速體驗

list1 = ['a', 'b', 'c', 'd', 'e']
?
for i in enumerate(list1):
    print(i)
?
for index, char in enumerate(list1, start=1):
    print(f'下標是{index}, 對應的字符是{char}')

容器型別轉換

tuple()

作用:將某個序列轉換成元組

list1 = [10, 20, 30, 40, 50, 20]
s1 = {100, 200, 300, 400, 500}
?
print(tuple(list1))
print(tuple(s1))

list()

作用:將某個序列轉換成串列

t1 = ('a', 'b', 'c', 'd', 'e')
s1 = {100, 200, 300, 400, 500}
?
print(list(t1))
print(list(s1))

set()

作用:將某個序列轉換成集合

list1 = [10, 20, 30, 40, 50, 20]
t1 = ('a', 'b', 'c', 'd', 'e')
?
print(set(list1))
print(set(t1))

注意:

  1. 集合可以快速完成串列去重

  2. 集合不支持下標

總結

  • 運算子

    • +

    • in / not in

  • 公共方法

    • len()

    • del()

    • range()

    • enumerate()

  • 資料型別轉換

    • tuple()

    • list()

    • set()

推導式

作用:用一個運算式創建一個有規律的串列或控制一個有規律串列,

串列推導式又叫串列生成式,

快速體驗

需求:創建一個0-10的串列,

  • while回圈實作

# 1. 準備一個空串列
list1 = []
?
# 2. 書寫回圈,依次追加數字到空串列list1中
i = 0
while i < 10:
    list1.append(i)
    i += 1
?
print(list1)
  • for回圈實作

list1 = []
for i in range(10):
    list1.append(i)
?
print(list1)
  • 串列推導式實作

list1 = [i for i in range(10)]
print(list1)

帶if的串列推導式

需求:創建0-10的偶數串列

  • 方法一:range()步長實作

list1 = [i for i in range(0, 10, 2)]
print(list1)
  • 方法二:if實作

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

多個for回圈實作串列推導式

需求:創建串列如下:

[(1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
  • 代碼如下:

list1 = [(i, j) for i in range(1, 3) for j in range(3)]
print(list1)

字典推導式

思考:如果有如下兩個串列:

list1 = ['name', 'age', 'gender']
list2 = ['Tom', 20, 'man']

如何快速合并為一個字典?

答:字典推導式

字典推導式作用:快速合并串列為字典或提取字典中目標資料,

快速體驗

  1. 創建一個字典:字典key是1-5數字,value是這個數字的2次方,

dict1 = {i: i**2 for i in range(1, 5)}
print(dict1)  # {1: 1, 2: 4, 3: 9, 4: 16}

  1. 將兩個串列合并為一個字典

list1 = ['name', 'age', 'gender']
list2 = ['Tom', 20, 'man']
?
dict1 = {list1[i]: list2[i] for i in range(len(list1))}
print(dict1)
  1. 提取字典中目標資料

counts = {'MBP': 268, 'HP': 125, 'DELL': 201, 'Lenovo': 199, 'acer': 99}
?
# 需求:提取上述電腦數量大于等于200的字典資料
count1 = {key: value for key, value in counts.items() if value >= 200}
print(count1)  # {'MBP': 268, 'DELL': 201}

集合推導式

需求:創建一個集合,資料為下方串列的2次方,

list1 = [1, 1, 2]

代碼如下:

list1 = [1, 1, 2]
set1 = {i ** 2 for i in list1}
print(set1)  # {1, 4}

注意:集合有資料去重功能,

總結

  • 推導式的作用:簡化代碼

  • 推導式寫法

# 串列推導式
[xx for xx in range()]
?
# 字典推導式
{xx1: xx2 for ... in ...}
?
# 集合推導式
{xx for xx in ...}

函式一

函式的作用

需求:用戶到ATM機取錢:

  1. 輸入密碼后顯示"選擇功能"界面

  2. 查詢余額后顯示"選擇功能"界面

  3. 取2000錢后顯示"選擇功能"界面

特點:顯示“選擇功能”界面需要重復輸出給用戶,怎么實作?

函式就是將==一段具有獨立功能的代碼塊== 整合到一個整體并命名,在需要的位置==呼叫這個名稱==即可完成對應的需求,

函式在開發程序中,可以更高效的實作==代碼重用==,

函式的使用步驟

定義函式

def 函式名(引數):
    代碼1
    代碼2
    ......

呼叫函式

函式名(引數)

注意:

  1. 不同的需求,引數可有可無,

  2. 在Python中,函式必須==先定義后使用==,

快速體驗

需求:復現ATM取錢功能,

  1. 搭建整體框架(復現需求)

print('密碼正確登錄成功')
?
# 顯示"選擇功能"界面
?
print('查詢余額完畢')
?
# 顯示"選擇功能"界面
?
print('取了2000元錢')
?
# 顯示"選擇功能"界面
  1. 確定“選擇功能”界面內容

print('查詢余額')
print('存款')
print('取款')
  1. 封裝"選擇功能"

注意:一定是先定義函式,后呼叫函式,

# 封裝ATM機功能選項 -- 定義函式
def select_func():
    print('-----請選擇功能-----')
    print('查詢余額')
    print('存款')
    print('取款')
    print('-----請選擇功能-----')
  1. 呼叫函式

在需要顯示“選擇功能”函式的位置呼叫函式,

print('密碼正確登錄成功')
# 顯示"選擇功能"界面 -- 呼叫函式
select_func()
?
print('查詢余額完畢')
# 顯示"選擇功能"界面 -- 呼叫函式
select_func()
?
print('取了2000元錢')
# 顯示"選擇功能"界面 -- 呼叫函式
select_func()

函式的引數作用

思考:完成需求如下:一個函式完成兩個數1和2的加法運算,如何書寫程式?

# 定義函式
def add_num1():
    result = 1 + 2
    print(result)
?
?
# 呼叫函式
add_num1()

思考:上述add_num1函式只能完成數字1和2的加法運算,如果想要這個函式變得更靈活,可以計算任何用戶指定的兩個數字的和,如何書寫程式?

分析:用戶要在呼叫函式的時候指定具體數字,那么在定義函式的時候就需要接收用戶指定的數字,函式呼叫時候指定的數字和定義函式時候接收的數字即是函式的引數,

# 定義函式時同時定義了接收用戶資料的引數a和b,a和b是形參
def add_num2(a, b):
    result = a + b
    print(result)
?
?
# 呼叫函式時傳入了真實的資料10 和 20,真實資料為實參
add_num2(10, 20)

函式的回傳值作用

例如:我們去超市購物,比如買煙,給錢之后,是不是售貨員會回傳給我們煙這個商品,在函式中,如果需要回傳結果給用戶需要使用函式回傳值,

def buy():
    return '煙'
?
# 使用變數保存函式回傳值
goods = buy()
print(goods)

應用

需求:制作一個計算器,計算任意兩數字之和,并保存結果,

def sum_num(a, b):
    return a + b
?
?
# 用result變數保存函式回傳值
result = sum_num(1, 2)
print(result)

函式的說明檔案

思考:定義一個函式后,程式員如何書寫程式能夠快速提示這個函式的作用?

答:注釋

思考:如果代碼多,我們是不是需要在很多代碼中找到這個函式定義的位置才能看到注釋?如果想更方便的查看函式的作用怎么辦?

答:函式的說明檔案

函式的說明檔案也叫函式的檔案說明,

語法

  • 定義函式的說明檔案

def 函式名(引數):
    """ 說明檔案的位置 """
    代碼
    ......
  • 查看函式的說明檔案

help(函式名)

快速體驗

def sum_num(a, b):
    """ 求和函式 """
    return a + b
?
?
help(sum_num)

函式嵌套呼叫

所謂函式嵌套呼叫指的是==一個函式里面又呼叫了另外一個函式==,

  • 示例

def testB():
    print('---- testB start----')
    print('這里是testB函式執行的代碼...(省略)...')
    print('---- testB end----')
?
def testA():
    print('---- testA start----')
    testB()
    print('---- testA end----')
?
testA()

  • 如果函式A中,呼叫了另外一個函式B,那么先把函式B中的任務都執行完畢之后才會回到上次 函式A執行的位置,

函式應用

函式計算

  1. 求三個數之和

def sum_num(a, b, c):
    return a + b + c
?
?
result = sum_num(1, 2, 3)
print(result)  # 6

  1. 求三個數平均值

def average_num(a, b, c):
    sumResult = sum_num(a, b, c)
    return sumResult / 3
?
result = average_num(1, 2, 3)
print(result)  # 2.0

總結

  • 函式的作用:封裝代碼,高效的代碼重用

  • 函式使用步驟

    • 定義函式

    def 函式名():
        代碼1
        代碼2
        ...
    • 呼叫函式

    函式名()
  • 函式的引數:函式呼叫的時候可以傳入真實資料,增大函式的使用的靈活性

    • 形參:函式定義時書寫的引數(非真實資料)

    • 實參:函式呼叫時書寫的引數(真實資料)

  • 函式的回傳值

    • 作用:函式呼叫后,回傳需要的計算結果

    • 寫法

    return 運算式
  • 函式的說明檔案

    • 作用:保存函式解釋說明的資訊

    • 寫法

    def 函式名():
        """ 函式說明檔案 """
  • 函式嵌套呼叫:一個函式內部嵌套呼叫另外一個函式

函式二

變數作用域

變數作用域指的是變數生效的范圍,主要分為兩類:==區域變數==和==全域變數==,

  • 區域變數

所謂區域變數是定義在函式體內部的變數,即只在函式體內部生效,

def testA():
    a = 100
?
    print(a)
?
?
testA()  # 100
print(a)  # 報錯:name 'a' is not defined

變數a是定義在testA函式內部的變數,在函式外部訪問則立即報錯,

區域變數的作用:在函式體內部,臨時保存資料,即當函式呼叫完成后,則銷毀區域變數,

  • 全域變數

所謂全域變數,指的是在函式體內、外都能生效的變數,

思考:如果有一個資料,在函式A和函式B中都要使用,該怎么辦?

答:將這個資料存盤在一個全域變數里面,

# 定義全域變數a
a = 100
?
?
def testA():
    print(a)  # 訪問全域變數a,并列印變數a存盤的資料
?
?
def testB():
    print(a)  # 訪問全域變數a,并列印變數a存盤的資料
?
?
testA()  # 100
testB()  # 100

思考:testB函式需求修改變數a的值為200,如何修改程式?

a = 100
?
?
def testA():
    print(a)
?
?
def testB():
    a = 200
    print(a)
?
?
testA()  # 100
testB()  # 200
print(f'全域變數a = {a}')  # 全域變數a = 100

思考:在testB函式內部的a = 200中的變數a是在修改全域變數a嗎?

答:不是,觀察上述代碼發現,15行得到a的資料是100,仍然是定義全域變數a時候的值,而沒有回傳

testB函式內部的200,綜上:testB函式內部的a = 200是定義了一個區域變數,

思考:如何在函式體內部修改全域變數?

a = 100
?
?
def testA():
    print(a)
?
?
def testB():
    # global 關鍵字宣告a是全域變數
    global a
    a = 200
    print(a)
?
?
testA()  # 100
testB()  # 200
print(f'全域變數a = {a}')  # 全域變數a = 200

多函式程式執行流程

一般在實際開發程序中,一個程式往往由多個函式(后面知識中會講解類)組成,并且多個函式共享某些資料,如下所示:

  • 共用全域變數

# 1. 定義全域變數
glo_num = 0
?
?
def test1():
    global glo_num
    # 修改全域變數
    glo_num = 100
?
?
def test2():
    # 呼叫test1函式中修改后的全域變數
    print(glo_num)
    
?
# 2. 呼叫test1函式,執行函式內部代碼:宣告和修改全域變數
test1()
# 3. 呼叫test2函式,執行函式內部代碼:列印
test2()  # 100
  • 回傳值作為引數傳遞

def test1():
    return 50
?
?
def test2(num):
    print(num)
?
?
# 1. 保存函式test1的回傳值
result = test1()
?
?
# 2.將函式回傳值所在變數作為引數傳遞到test2函式
test2(result)  # 50

函式的回傳值

思考:如果一個函式如些兩個return (如下所示),程式如何執行?

def return_num():
    return 1
    return 2
?
?
result = return_num()
print(result)  # 1

答:只執行了第一個return,原因是因為return可以退出當前函式,導致return下方的代碼不執行,

思考:如果一個函式要有多個回傳值,該如何書寫代碼?

def return_num():
    return 1, 2
?
?
result = return_num()
print(result)  # (1, 2)

注意:

  1. return a, b寫法,回傳多個資料的時候,默認是元組型別,

  2. return后面可以連接串列、元組或字典,以回傳多個值,

函式的引數

位置引數

位置引數:呼叫函式時根據函式定義的引數位置來傳遞引數,

def user_info(name, age, gender):
    print(f'您的名字是{name}, 年齡是{age}, 性別是{gender}')
?
?
user_info('TOM', 20, '男')

注意:傳遞和定義引數的順序及個數必須一致,

關鍵字引數

函式呼叫,通過“鍵=值”形式加以指定,可以讓函式更加清晰、容易使用,同時也清除了引數的順序需求,

def user_info(name, age, gender):
    print(f'您的名字是{name}, 年齡是{age}, 性別是{gender}')
?
?
user_info('Rose', age=20, gender='女')
user_info('小明', gender='男', age=16)

注意:函式呼叫時,如果有位置引數時,位置引數必須在關鍵字引數的前面,但關鍵字引數之間不存在先后順序,

預設引數

預設引數也叫默認引數,用于定義函式,為引數提供默認值,呼叫函式時可不傳該默認引數的值(注意:所有位置引數必須出現在默認引數前,包括函式定義和呼叫),

def user_info(name, age, gender='男'):
    print(f'您的名字是{name}, 年齡是{age}, 性別是{gender}')
?
?
user_info('TOM', 20)
user_info('Rose', 18, '女')

注意:函式呼叫時,如果為預設引數傳值則修改默認引數值;否則使用這個默認值,

不定長引數

不定長引數也叫可變引數,用于不確定呼叫的時候會傳遞多少個引數(不傳參也可以)的場景,此時,可用包裹(packing)位置引數,或者包裹關鍵字引數,來進行引數傳遞,會顯得非常方便,

  • 包裹位置傳遞

def user_info(*args):
    print(args)
?
?
# ('TOM',)
user_info('TOM')
# ('TOM', 18)
user_info('TOM', 18)

注意:傳進的所有引數都會被args變數收集,它會根據傳進引數的位置合并為一個元組(tuple),args是元組型別,這就是包裹位置傳遞,

  • 包裹關鍵字傳遞

def user_info(**kwargs):
    print(kwargs)
?
?
# {'name': 'TOM', 'age': 18, 'id': 110}
user_info(name='TOM', age=18, id=110)

綜上:無論是包裹位置傳遞還是包裹關鍵字傳遞,都是一個組包的程序,

拆包和交換變數值

拆包

  • 拆包:元組

def return_num():
    return 100, 200
?
?
num1, num2 = return_num()
print(num1)  # 100
print(num2)  # 200
  • 拆包:字典

dict1 = {'name': 'TOM', 'age': 18}
a, b = dict1
?
# 對字典進行拆包,取出來的是字典的key
print(a)  # name
print(b)  # age
?
print(dict1[a])  # TOM
print(dict1[b])  # 18

交換變數值

需求:有變數a = 10b = 20,交換兩個變數的值,

  • 方法一

借助第三變數存盤資料,

# 1. 定義中間變數
c = 0
?
# 2. 將a的資料存盤到c
c = a
?
# 3. 將b的資料20賦值到a,此時a = 20
a = b
?
# 4. 將之前c的資料10賦值到b,此時b = 10
b = c
?
print(a)  # 20
print(b)  # 10
  • 方法二

a, b = 1, 2
a, b = b, a
print(a)  # 2
print(b)  # 1

參考

了解參考

在python中,值是靠參考來傳遞來的,

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

# 1. int型別
a = 1
b = a
?
print(b)  # 1
?
print(id(a))  # 140708464157520
print(id(b))  # 140708464157520
?
a = 2
print(b)  # 1,說明int型別為不可變型別 
?
print(id(a))  # 140708464157552,此時得到是的資料2的記憶體地址
print(id(b))  # 140708464157520
?
?
# 2. 串列
aa = [10, 20]
bb = aa
?
print(id(aa))  # 2325297783432
print(id(bb))  # 2325297783432
?
?
aa.append(30)
print(bb)  # [10, 20, 30], 串列為可變型別
?
print(id(aa))  # 2325297783432
print(id(bb))  # 2325297783432

參考當做實參

代碼如下:

def test1(a):
    print(a)
    print(id(a))
?
    a += a
?
    print(a)
    print(id(a))
?
?
# int:計算前后id值不同
b = 100
test1(b)
?
# 串列:計算前后id值相同
c = [11, 22]
test1(c)

可變和不可變型別

所謂可變型別與不可變型別是指:資料能夠直接進行修改,如果能直接修改那么就是可變,否則是不可變.

  • 可變型別

    • 串列

    • 字典

    • 集合

  • 不可變型別

    • 整型

    • 浮點型

    • 字串

    • 元組

總結

  • 變數作用域

    • 全域:函式體內外都能生效

    • 區域:當前函式體內部生效

  • 函式多回傳值寫法

return 運算式1, 運算式2...
  • 函式的引數

    • 位置引數

      • 形參和實參的個數和書寫順序必須一致

    • 關鍵字引數

      • 寫法: key=value

      • 特點:形參和實參的書寫順序可以不一致;關鍵字引數必須書寫在位置引數的后面

    • 預設引數

      • 預設引數就是默認引數

      • 寫法:key=vlaue

    • 不定長位置引數

      • 收集所有位置引數,回傳一個元組

    • 不定長關鍵字引數

      • 收集所有關鍵字引數,回傳一個字典

  • 參考:Python中,資料的傳遞都是通過參考

函式三

應用:學員管理系統

系統簡介

需求:進入系統顯示系統功能界面,功能如下:

  • 1、添加學員

  • 2、洗掉學員

  • 3、修改學員資訊

  • 4、查詢學員資訊

  • 5、顯示所有學員資訊

  • 6、退出系統

系統共6個功能,用戶根據自己需求選取,

步驟分析

  1. 顯示功能界面

  2. 用戶輸入功能序號

  3. 根據用戶輸入的功能序號,執行不同的功能(函式)

    3.1 定義函式

    3.2 呼叫函式

需求實作

顯示功能界面

定義函式print_info,負責顯示系統功能,

def print_info():
    print('-' * 20)
    print('歡迎登錄學員管理系統')
    print('1: 添加學員')
    print('2: 洗掉學員')
    print('3: 修改學員資訊')
    print('4: 查詢學員資訊')
    print('5: 顯示所有學員資訊')
    print('6: 退出系統')
    print('-' * 20)
    
    
print_info()

用戶輸入序號,選擇功能

user_num = input('請選擇您需要的功能序號:')

根據用戶選擇,執行不同的功能

if user_num == '1':
    print('添加學員')
elif user_num == '2':
    print('洗掉學員')
elif user_num == '3':
    print('修改學員資訊')
elif user_num == '4':
    print('查詢學員資訊')
elif user_num == '5':
    print('顯示所有學員資訊')
elif user_num == '6':
    print('退出系統')

作業中,需要根據實際需求調優代碼,

  1. 用戶選擇系統功能的代碼需要回圈使用,直到用戶主動退出系統,

  2. 如果用戶輸入1-6以外的數字,需要提示用戶,

while True:
    # 1. 顯示功能界面
    print_info()
    
    # 2. 用戶選擇功能
    user_num = input('請選擇您需要的功能序號:')
?
    # 3. 根據用戶選擇,執行不同的功能
    if user_num == '1':
        print('添加學員')
    elif user_num == '2':
        print('洗掉學員')
    elif user_num == '3':
        print('修改學員資訊')
    elif user_num == '4':
        print('查詢學員資訊')
    elif user_num == '5':
        print('顯示所有學員資訊')
    elif user_num == '6':
        print('退出系統')
    else:
        print('輸入錯誤,請重新輸入!!!')

定義不同功能的函式

所有功能函式都是操作學員資訊,所有存盤所有學員資訊應該是一個==全域變數==,資料型別為==串列==,

info = []

1.3.4.1 添加學員

  • 需求分析

  1. 接收用戶輸入學員資訊,并保存

  2. 判斷是否添加學員資訊

    2.1 如果學員姓名已經存在,則報錯提示

    2.2 如果學員姓名不存在,則準備空字典,將用戶輸入的資料追加到字典,再串列追加字典資料

  3. 對應的if條件成立的位置呼叫該函式

  • 代碼實作

def add_info():
    """ 添加學員 """
    # 接收用戶輸入學員資訊
    new_id = input('請輸入學號:')
    new_name = input('請輸入姓名:')
    new_tel = input('請輸入手機號:')
    
?
    # 宣告info是全域變數
    global info
?
    # 檢測用戶輸入的姓名是否存在,存在則報錯提示
    for i in info:
        if new_name == i['name']:
            print('該用戶已經存在!')
            return
?
    # 如果用戶輸入的姓名不存在,則添加該學員資訊
    info_dict = {}
    
    # 將用戶輸入的資料追加到字典
    info_dict['id'] = new_id
    info_dict['name'] = new_name
    info_dict['tel'] = new_tel
    
    # 將這個學員的字典資料追加到串列
    info.append(info_dict)
    
    print(info)

洗掉學員

  • 需求分析

按用戶輸入的學員姓名進行洗掉

  1. 用戶輸入目標學員姓名

  2. 檢查這個學員是否存在

    2.1 如果存在,則串列洗掉這個資料

    2.2 如果不存在,則提示“該用戶不存在”

  3. 對應的if條件成立的位置呼叫該函式

  • 代碼實作

# 洗掉學員
def del_info():
    """洗掉學員"""
    # 1. 用戶輸入要洗掉的學員的姓名
    del_name = input('請輸入要洗掉的學員的姓名:')
?
    global info
    # 2. 判斷學員是否存在:如果輸入的姓名存在則洗掉,否則報錯提示
    for i in info:
        if del_name == i['name']:
            info.remove(i)
            break
    else:
        print('該學員不存在')
?
    print(info)

修改學員資訊

  • 需求分析

  1. 用戶輸入目標學員姓名

  2. 檢查這個學員是否存在

    2.1 如果存在,則修改這位學員的資訊,例如手機號

    2.2 如果不存在,則報錯

  3. 對應的if條件成立的位置呼叫該函式

  • 代碼實作

# 修改函式
def modify_info():
    """修改函式"""
    # 1. 用戶輸入要修改的學員的姓名
    modify_name = input('請輸入要修改的學員的姓名:')
?
    global info
    # 2. 判斷學員是否存在:如果輸入的姓名存在則修改手機號,否則報錯提示
    for i in info:
        if modify_name == i ['name']:
            i['tel'] = input('請輸入新的手機號:')
            break
    else:
        print('該學員不存在')
    
    print(info)

查詢學員資訊

  • 需求分析

  1. 用戶輸入目標學員姓名

  2. 檢查學員是否存在

    2.1 如果存在,則顯示這個學員的資訊

    2.2 如果不存在,則報錯提示

  3. 對應的if條件成立的位置呼叫該函式

  • 代碼實作

# 查詢學員
def search_info():
    """查詢學員"""
    # 1. 輸入要查找的學員姓名:
    search_name = input('請輸入要查找的學員姓名:')
?
    global info
    # 2. 判斷學員是否存在:如果輸入的姓名存在則顯示這位學員資訊,否則報錯提示
    for i in info:
        if search_name == i['name']:
            print('查找到的學員資訊如下:----------')
            print(f"該學員的學號是{i['id']}, 姓名是{i['name']}, 手機號是{i['tel']}")
            break
    else:
        print('該學員不存在')

顯示所有學員資訊

  • 需求分析

列印所有學員資訊

  • 代碼實作

# 顯示所有學員資訊
def print_all():
    """ 顯示所有學員資訊 """
    print('學號\t姓名\t手機號')
    for i in info:
        print(f'{i["id"]}\t{i["name"]}\t{i["tel"]}')

1.3.4.6 退出系統

在用戶輸入功能序號6的時候要退出系統,代碼如下:

    ......
    elif user_num == '6':
        exit_flag = input('確定要退出嗎?yes or no')
        if exit_flag == 'yes':
            break

遞回

遞回是一種編程思想,應用場景:

  1. 在我們日常開發中,如果要遍歷一個檔案夾下面所有的檔案,通常會使用遞回來實作;

  2. 在后續的演算法課程中,很多演算法都離不開遞回,例如:快速排序,

遞回的特點

  • 函式內部自己呼叫自己

  • 必須有出口

應用:3以內數字累加和

  • 代碼

# 3 + 2 + 1
def sum_numbers(num):
    # 1.如果是1,直接回傳1 -- 出口
    if num == 1:
        return 1
    # 2.如果不是1,重復執行累加并回傳結果
    return num + sum_numbers(num-1)
?
?
sum_result = sum_numbers(3)
# 輸出結果為6
print(sum_result)

lambda 運算式

如果一個函式有一個回傳值,并且只有一句代碼,可以使用 lambda簡化,

lambda語法

lambda 引數串列 : 運算式

注意

  • lambda運算式的引數可有可無,函式的引數在lambda運算式中完全適用,

  • lambda運算式能接收任何數量的引數但只能回傳一個運算式的值,

快速入門

# 函式
def fn1():
    return 200
?
?
print(fn1)
print(fn1())
?
?
# lambda運算式
fn2 = lambda: 100
print(fn2)
print(fn2())

注意:直接列印lambda運算式,輸出的是此lambda的記憶體地址

示例:計算a + b

函式實作

def add(a, b):
    return a + b
?
?
result = add(1, 2)
print(result)

思考:需求簡單,是否代碼多?

lambda實作

fn1 = lambda a, b: a + b
print(fn1(1, 2))

lambda的引數形式

無引數

fn1 = lambda: 100
print(fn1())

一個引數

fn1 = lambda a: a
print(fn1('hello world'))

默認引數

fn1 = lambda a, b, c=100: a + b + c
print(fn1(10, 20))

可變引數:*args

fn1 = lambda *args: args
print(fn1(10, 20, 30))

注意:這里的可變引數傳入到lambda之后,回傳值為元組,

可變引數:**kwargs

fn1 = lambda **kwargs: kwargs
print(fn1(name='python', age=20))

lambda的應用

帶判斷的lambda

fn1 = lambda a, b: a if a > b else b
print(fn1(1000, 500))

串列資料按字典key的值排序

students = [
    {'name': 'TOM', 'age': 20},
    {'name': 'ROSE', 'age': 19},
    {'name': 'Jack', 'age': 22}
]
?
# 按name值升序排列
students.sort(key=lambda x: x['name'])
print(students)
?
# 按name值降序排列
students.sort(key=lambda x: x['name'], reverse=True)
print(students)
?
# 按age值升序排列
students.sort(key=lambda x: x['age'])
print(students)

高階函式

==把函式作為引數傳入==,這樣的函式稱為高階函式,高階函式是函式式編程的體現,函式式編程就是指這種高度抽象的編程范式,

體驗高階函式

在Python中,abs()函式可以完成對數字求絕對值計算,

abs(-10)  # 10

round()函式可以完成對數字的四舍五入計算,

round(1.2)  # 1
round(1.9)  # 2

需求:任意兩個數字,按照指定要求整理數字后再進行求和計算,

  • 方法1

def add_num(a, b):
    return abs(a) + abs(b)
?
?
result = add_num(-1, 2)
print(result)  # 3
  • 方法2

def sum_num(a, b, f):
    return f(a) + f(b)
?
?
result = sum_num(-1, 2, abs)
print(result)  # 3

注意:兩種方法對比之后,發現,方法2的代碼會更加簡潔,函式靈活性更高,

函式式編程大量使用函式,減少了代碼的重復,因此程式比較短,開發速度較快,

內置高階函式

map()

map(func, lst),將傳入的函式變數func作用到lst變數的每個元素中,并將結果組成新的串列(Python2)/迭代器(Python3)回傳,

需求:計算list1序列中各個數字的2次方,

list1 = [1, 2, 3, 4, 5]
?
?
def func(x):
    return x ** 2
?
?
result = map(func, list1)
?
print(result)  # <map object at 0x0000013769653198>
print(list(result))  # [1, 4, 9, 16, 25]

reduce()

reduce(func,lst),其中func必須有兩個引數,每次func計算的結果繼續和序列的下一個元素做累積計算,

注意:reduce()傳入的引數func必須接收2個引數,

需求:計算list1序列中各個數字的累加和,

import functools
?
list1 = [1, 2, 3, 4, 5]
?
?
def func(a, b):
    return a + b
?
?
result = functools.reduce(func, list1)
?
print(result)  # 15

filter()

filter(func, lst)函式用于過濾序列, 過濾掉不符合條件的元素, 回傳一個 filter 物件,如果要轉換為串列, 可以使用 list() 來轉換,

list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
?
?
def func(x):
    return x % 2 == 0
?
?
result = filter(func, list1)
?
print(result)  # <filter object at 0x0000017AF9DC3198>
print(list(result))  # [2, 4, 6, 8, 10]

總結

  • 遞回

    • 函式內部自己呼叫自己

    • 必須有出口

  • lambda

    • 語法

    lambda 引數串列: 運算式
    • lambda的引數形式

      • 無引數

      lambda: 運算式
      • 一個引數

      lambda 引數: 運算式
      • 默認引數

      lambda key=value: 運算式
      • 不定長位置引數

      lambda *args: 運算式
      • 不定長關鍵字引數

      lambda **kwargs: 運算式
  • 高階函式

    • 作用:把函式作為引數傳入,化簡代碼

    • 內置高階函式

      • map()

      • reduce()

      • filter()

檔案操作

檔案操作的作用

思考:什么是檔案?

思考:檔案操作包含什么?

答:打開、關閉、讀、寫、復制....

思考:檔案操作的的作用是什么?

答:讀取內容、寫入內容、備份內容......

總結:檔案操作的作用就是==把一些內容(資料)存盤存放起來,可以讓程式下一次執行的時候直接使用,而不必重新制作一份,省時省力==,

檔案的基本操作

檔案操作步驟

  1. 打開檔案

  2. 讀寫等操作

  3. 關閉檔案

注意:可以只打開和關閉檔案,不進行任何讀寫操作,

打開

在python,使用open函式,可以打開一個已經存在的檔案,或者創建一個新檔案,語法如下:

open(name, mode)

name:是要打開的目標檔案名的字串(可以包含檔案所在的具體路徑),

mode:設定打開檔案的模式(訪問模式):只讀、寫入、追加等,

打開檔案模式

模式描述
r以只讀方式打開檔案,檔案的指標將會放在檔案的開頭,這是默認模式,
rb以二進制格式打開一個檔案用于只讀,檔案指標將會放在檔案的開頭,這是默認模式,
r+打開一個檔案用于讀寫,檔案指標將會放在檔案的開頭,
rb+以二進制格式打開一個檔案用于讀寫,檔案指標將會放在檔案的開頭,
w打開一個檔案只用于寫入,如果該檔案已存在則打開檔案,并從開頭開始編輯,即原有內容會被洗掉,如果該檔案不存在,創建新檔案,
wb以二進制格式打開一個檔案只用于寫入,如果該檔案已存在則打開檔案,并從開頭開始編輯,即原有內容會被洗掉,如果該檔案不存在,創建新檔案,
w+打開一個檔案用于讀寫,如果該檔案已存在則打開檔案,并從開頭開始編輯,即原有內容會被洗掉,如果該檔案不存在,創建新檔案,
wb+以二進制格式打開一個檔案用于讀寫,如果該檔案已存在則打開檔案,并從開頭開始編輯,即原有內容會被洗掉,如果該檔案不存在,創建新檔案,
a打開一個檔案用于追加,如果該檔案已存在,檔案指標將會放在檔案的結尾,也就是說,新的內容將會被寫入到已有內容之后,如果該檔案不存在,創建新檔案進行寫入,
ab以二進制格式打開一個檔案用于追加,如果該檔案已存在,檔案指標將會放在檔案的結尾,也就是說,新的內容將會被寫入到已有內容之后,如果該檔案不存在,創建新檔案進行寫入,
a+打開一個檔案用于讀寫,如果該檔案已存在,檔案指標將會放在檔案的結尾,檔案打開時會是追加模式,如果該檔案不存在,創建新檔案用于讀寫,
ab+以二進制格式打開一個檔案用于追加,如果該檔案已存在,檔案指標將會放在檔案的結尾,如果該檔案不存在,創建新檔案用于讀寫,

快速體驗

f = open('test.txt', 'w')

注意:此時的fopen函式的檔案物件,

檔案物件方法

  • 語法

物件物件.write('內容')
  • 體驗

# 1. 打開檔案
f = open('test.txt', 'w')
?
# 2.檔案寫入
f.write('hello world')
?
# 3. 關閉檔案
f.close()

注意:

  1. wa模式:如果檔案不存在則創建該檔案;如果檔案存在,w模式先清空再寫入,a模式直接末尾追加,

  2. r模式:如果檔案不存在則報錯,

  • read()

檔案物件.read(num)

num表示要從檔案中讀取的資料的長度(單位是位元組),如果沒有傳入num,那么就表示讀取檔案中所有的資料,

  • readlines()

readlines可以按照行的方式把整個檔案中的內容進行一次性讀取,并且回傳的是一個串列,其中每一行的資料為一個元素,

f = open('test.txt')
content = f.readlines()
?
# ['hello world\n', 'abcdefg\n', 'aaa\n', 'bbb\n', 'ccc']
print(content)
?
# 關閉檔案
f.close()

  • readline()

readline()一次讀取一行內容,

f = open('test.txt')
?
content = f.readline()
print(f'第一行:{content}')
?
content = f.readline()
print(f'第二行:{content}')
?
# 關閉檔案
f.close()

seek()

作用:用來移動檔案指標,

語法如下:

檔案物件.seek(偏移量, 起始位置)

起始位置:

  • 0:檔案開頭

  • 1:當前位置

  • 2:檔案結尾

關閉

檔案物件.close()

檔案備份

需求:用戶輸入當前目錄下任意檔案名,程式完成對該檔案的備份功能(備份檔案名為xx[備份]后綴,例如:test[備份].txt),

步驟

  1. 接收用戶輸入的檔案名

  2. 規劃備份檔案名

  3. 備份檔案寫入資料

代碼實作

  1. 接收用戶輸入目標檔案名

old_name = input('請輸入您要備份的檔案名:')

  1. 規劃備份檔案名

    2.1 提取目標檔案后綴

    2.2 組織備份的檔案名,xx[備份]后綴

# 2.1 提取檔案后綴點的下標
index = old_name.rfind('.')
?
# print(index)  # 后綴中.的下標
?
# print(old_name[:index])  # 源檔案名(無后綴)
?
# 2.2 組織新檔案名 舊檔案名 + [備份] + 后綴
new_name = old_name[:index] + '[備份]' + old_name[index:]
?
# 列印新檔案名(帶后綴)
# print(new_name)
  1. 備份檔案寫入資料

    3.1 打開源檔案 和 備份檔案

    3.2 將源檔案資料寫入備份檔案

    3.3 關閉檔案

# 3.1 打開檔案
old_f = open(old_name, 'rb')
new_f = open(new_name, 'wb')
?
# 3.2 將源檔案資料寫入備份檔案
while True:
    con = old_f.read(1024)
    if len(con) == 0:
        break
    new_f.write(con)
?
# 3.3 關閉檔案
old_f.close()
new_f.close()

思考

如果用戶輸入.txt,這是一個無效檔案,程式如何更改才能限制只有有效的檔案名才能備份?

答:添加條件判斷即可,

old_name = input('請輸入您要備份的檔案名:')
?
index = old_name.rfind('.')
?
?
if index > 0:
    postfix = old_name[index:]
?
new_name = old_name[:index] + '[備份]' + postfix
?
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)
?
old_f.close()
new_f.close()

檔案和檔案夾的操作

在Python中檔案和檔案夾的操作要借助os模塊里面的相關功能,具體步驟如下:

  1. 匯入os模塊

import os
  1. 使用os模塊相關功能

os.函式名()

檔案重命名

os.rename(目標檔案名, 新檔案名)

洗掉檔案

os.remove(目標檔案名)

創建檔案夾

os.mkdir(檔案夾名字)

洗掉檔案夾

os.rmdir(檔案夾名字)

獲取當前目錄

os.getcwd()

改變默認目錄

os.chdir(目錄)

獲取目錄串列

os.listdir(目錄)

應用案例

需求:批量修改檔案名,既可添加指定字串,又能洗掉指定字串,

  • 步驟

  1. 設定添加洗掉字串的的標識

  2. 獲取指定目錄的所有檔案

  3. 將原有檔案名添加/洗掉指定字串,構造新名字

  4. os.rename()重命名

  • 代碼

import os
?
# 設定重命名標識:如果為1則添加指定字符,flag取值為2則洗掉指定字符
flag = 1
?
# 獲取指定目錄
dir_name = './'
?
# 獲取指定目錄的檔案串列
file_list = os.listdir(dir_name)
# print(file_list)
?
?
# 遍歷檔案串列內的檔案
for name in file_list:
?
    # 添加指定字符
    if flag == 1:
        new_name = 'Python-' + name
    # 洗掉指定字符
    elif flag == 2:
        num = len('Python-')
        new_name = name[num:]
?
    # 列印新檔案名,測驗程式正確性
    print(new_name)
    
    # 重命名
    os.rename(dir_name+name, dir_name+new_name)

總結

  • 檔案操作步驟

    • 打開

    檔案物件 = open(目標檔案, 訪問模式)
    • 操作

      檔案物件.read()
      檔案物件.readlines()
      檔案物件.readline()
      檔案物件.write()
      • seek()

    • 關閉

    檔案物件.close()
  • 主訪問模式

    • w:寫,檔案不存在則新建該檔案

    • r:讀,檔案不存在則報錯

    • a:追加

  • 檔案和檔案夾操作

    • 重命名:os.rename()

    • 獲取當前目錄:os.getcwd()

    • 獲取目錄串列:os.listdir()

面向物件基礎

理解面向物件

面向物件是一種抽象化的編程思想,很多編程語言中都有的一種思想,

總結:==面向物件就是將編程當成是一個事物,對外界來說,事物是直接使用的,不用去管他內部的情況,而編程就是設定事物能夠做什么事,==

類和物件

在面向物件編程程序中,有兩個重要組成部分:類 和 物件

類和物件的關系:用類去創建一個物件,

理解類和物件

類是對一系列具有相同==特征==和==行為==的事物的統稱,是一個==抽象的概念==,不是真實存在的事物,

  • 特征即是屬性

  • 行為即是方法

物件

物件是類創建出來的真實存在的事物

注意:開發中,先有類,再有物件,

面向物件實作方法

定義類

Python2中類分為:經典類 和 新式類

  • 語法

class 類名():
    代碼
    ......

注意:類名要滿足識別符號命名規則,同時遵循==大駝峰命名習慣==,

  • 體驗

class Washer():
    def wash(self):
        print('我會洗衣服')
  • 拓展:經典類

不由任意內置型別派生出的類,稱之為經典類

class 類名:
    代碼
    ......

創建物件

物件又名實體,

  • 語法

物件名 = 類名()
  • 體驗

# 創建物件
haier1 = Washer()
?
# <__main__.Washer object at 0x0000018B7B224240>
print(haier1)
?
# haier物件呼叫實體方法
haier1.wash()

注意:創建物件的程序也叫實體化物件,

self

self指的是呼叫該函式的物件,

# 1. 定義類
class Washer():
    def wash(self):
        print('我會洗衣服')
        # <__main__.Washer object at 0x0000024BA2B34240>
        print(self)
?
?
# 2. 創建物件
haier1 = Washer()
# <__main__.Washer object at 0x0000018B7B224240>
print(haier1)
# haier1物件呼叫實體方法
haier1.wash()
?
?
haier2 = Washer()
# <__main__.Washer object at 0x0000022005857EF0>
print(haier2)

注意:列印物件和self得到的結果是一致的,都是當前物件的記憶體中存盤地址,

添加和獲取物件屬性

物件屬性既可以在類外面添加和獲取,也能在類里面添加和獲取,

類外面添加物件屬性語法

物件名.屬性名 = 值
  • 體驗

haier1.width = 500
haier1.height = 800

類外面獲取物件屬性

  • 語法

物件名.屬性名
  • 體驗

print(f'haier1洗衣機的寬度是{haier1.width}')
print(f'haier1洗衣機的高度是{haier1.height}')

類里面獲取物件屬性

  • 語法

self.屬性名
  • 體驗

# 定義類
class Washer():
    def print_info(self):
        # 類里面獲取實體屬性
        print(f'haier1洗衣機的寬度是{self.width}')
        print(f'haier1洗衣機的高度是{self.height}')
?
# 創建物件
haier1 = Washer()
?
# 添加實體屬性
haier1.width = 500
haier1.height = 800
?
haier1.print_info()

魔法方法

在Python中,__xx__()的函式叫做魔法方法,指的是具有特殊功能的函式,

__init__()

體驗__init__()

==__init__()方法的作用:初始化物件,==

class Washer():
    
    # 定義初始化功能的函式
    def __init__(self):
        # 添加實體屬性
        self.width = 500
        self.height = 800
?
?
    def print_info(self):
        # 類里面呼叫實體屬性
        print(f'洗衣機的寬度是{self.width}, 高度是{self.height}')
?
?
haier1 = Washer()
haier1.print_info()

注意:

  • __init__()方法,在創建一個物件時默認被呼叫,不需要手動呼叫

  • __init__(self)中的self引數,不需要開發者傳遞,python解釋器會自動把當前的物件參考傳遞過去,

帶引數的__init__()

思考:一個類可以創建多個物件,如何對不同的物件設定不同的初始化屬性呢?

答:傳引數,

class Washer():
    def __init__(self, width, height):
        self.width = width
        self.height = height
?
    def print_info(self):
        print(f'洗衣機的寬度是{self.width}')
        print(f'洗衣機的高度是{self.height}')
?
?
haier1 = Washer(10, 20)
haier1.print_info()
?
?
haier2 = Washer(30, 40)
haier2.print_info()

__str__()

當使用print輸出物件的時候,默認列印物件的記憶體地址,如果類定義了__str__方法,那么就會列印從在這個方法中 return 的資料,

class Washer():
    def __init__(self, width, height):
        self.width = width
        self.height = height
?
    def __str__(self):
        return '這是海爾洗衣機的說明書'
?
?
haier1 = Washer(10, 20)
# 這是海爾洗衣機的說明書
print(haier1)

__del__()

當洗掉物件時,python解釋器也會默認呼叫__del__()方法,

class Washer():
    def __init__(self, width, height):
        self.width = width
        self.height = height
?
    def __del__(self):
        print(f'{self}物件已經被洗掉')
?
?
haier1 = Washer(10, 20)
?
# <__main__.Washer object at 0x0000026118223278>物件已經被洗掉
del haier1

綜合應用

烤地瓜

需求

需求主線:

  1. 被烤的時間和對應的地瓜狀態:

    0-3分鐘:生的

    3-5分鐘:半生不熟

    5-8分鐘:熟的

    超過8分鐘:烤糊了

  2. 添加的調料:

    用戶可以按自己的意愿添加調料

步驟分析

需求涉及一個事物: 地瓜,故案例涉及一個類:地瓜類,

5.1.2.1 定義類

  • 地瓜的屬性

    • 被烤的時間

    • 地瓜的狀態

    • 添加的調料

  • 地瓜的方法

    • 被烤

      • 用戶根據意愿設定每次烤地瓜的時間

      • 判斷地瓜被烤的總時間是在哪個區間,修改地瓜狀態

    • 添加調料

      • 用戶根據意愿設定添加的調料

      • 將用戶添加的調料存盤

  • 顯示物件資訊

5.1.2.2 創建物件,呼叫相關實體方法

代碼實作

5.1.3.1 定義類

  • 地瓜屬性

    • 定義地瓜初始化屬性,后期根據程式推進更新實體屬性

class SweetPotato():
    def __init__(self):
        # 被烤的時間
        self.cook_time = 0
        # 地瓜的狀態
        self.cook_static = '生的'
        # 調料串列
        self.condiments = []

5.1.3.2 定義烤地瓜方法

class SweetPotato():
    ......
    
    def cook(self, time):
        """烤地瓜的方法"""
        self.cook_time += time
        if 0 <= self.cook_time < 3:
            self.cook_static = '生的'
        elif 3 <= self.cook_time < 5:
            self.cook_static = '半生不熟'
        elif 5 <= self.cook_time < 8:
            self.cook_static = '熟了'
        elif self.cook_time >= 8:
            self.cook_static = '烤糊了'

5.1.3.3 書寫str魔法方法,用于輸出物件狀態

class SweetPotato():
        ......
?
    def __str__(self):
        return f'這個地瓜烤了{self.cook_time}分鐘, 狀態是{self.cook_static}'
?

5.1.3.4 創建物件,測驗實體屬性和實體方法

digua1 = SweetPotato()
print(digua1)
digua1.cook(2)
print(digua1)

5.1.3.5 定義添加調料方法,并呼叫該實體方法

class SweetPotato():
        ......
?
    def add_condiments(self, condiment):
        """添加調料"""
        self.condiments.append(condiment)
    def __str__(self):
        return f'這個地瓜烤了{self.cook_time}分鐘, 狀態是{self.cook_static}, 添加的調料有{self.condiments}'
      
?
digua1 = SweetPotato()
print(digua1)
?
digua1.cook(2)
digua1.add_condiments('醬油')
print(digua1)
?
digua1.cook(2)
digua1.add_condiments('辣椒面兒')
print(digua1)
?
digua1.cook(2)
print(digua1)
?
digua1.cook(2)
print(digua1)

代碼總覽

# 定義類
class SweetPotato():
    def __init__(self):
        # 被烤的時間
        self.cook_time = 0
        # 地瓜的狀態
        self.cook_static = '生的'
        # 調料串列
        self.condiments = []
?
    def cook(self, time):
        """烤地瓜的方法"""
        self.cook_time += time
        if 0 <= self.cook_time < 3:
            self.cook_static = '生的'
        elif 3 <= self.cook_time < 5:
            self.cook_static = '半生不熟'
        elif 5 <= self.cook_time < 8:
            self.cook_static = '熟了'
        elif self.cook_time >= 8:
            self.cook_static = '烤糊了'
?
    def add_condiments(self, condiment):
        """添加調料"""
        self.condiments.append(condiment)
?
    def __str__(self):
        return f'這個地瓜烤了{self.cook_time}分鐘, 狀態是{self.cook_static}, 添加的調料有{self.condiments}'
?
?
digua1 = SweetPotato()
print(digua1)
?
digua1.cook(2)
digua1.add_condiments('醬油')
print(digua1)
?
digua1.cook(2)
digua1.add_condiments('辣椒面兒')
print(digua1)
?
digua1.cook(2)
print(digua1)
?
digua1.cook(2)
print(digua1)

搬家具

需求

將小于房子剩余面積的家具擺放到房子中

步驟分析

需求涉及兩個事物:房子 和 家具,故被案例涉及兩個類:房子類 和 家具類,

5.2.2.1 定義類

  • 房子類

    • 實體屬性

      • 房子地理位置

      • 房子占地面積

      • 房子剩余面積

      • 房子內家具串列

    • 實體方法

      • 容納家具

    • 顯示房屋資訊

  • 家具類

    • 家具名稱

    • 家具占地面積

5.2.2.2 創建物件并呼叫相關方法

代碼實作

5.2.3.1 定義類

  • 家具類

class Furniture():
    def __init__(self, name, area):
        # 家具名字
        self.name = name
        # 家具占地面積
        self.area = area

  • 房子類

class Home():
    def __init__(self, address, area):
        # 地理位置
        self.address = address
        # 房屋面積
        self.area = area
        # 剩余面積
        self.free_area = area
        # 家具串列
        self.furniture = []
?
    def __str__(self):
        return f'房子坐落于{self.address}, 占地面積{self.area}, 剩余面積{self.free_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('家具太大,剩余面積不足,無法容納')

創建物件并呼叫實體屬性和方法

bed = Furniture('雙人床', 6)
jia1 = Home('北京', 1200)
print(jia1)
?
jia1.add_furniture(bed)
print(jia1)
?
sofa = Furniture('沙發', 10)
jia1.add_furniture(sofa)
print(jia1)
?
ball = Furniture('籃球場', 1500)
jia1.add_furniture(ball)
print(jia1)

總結

  • 面向物件重要組成部分

      • 創建類

    class 類名():
      代碼
    • 物件

    物件名 = 類名()
  • 添加物件屬性

    • 類外面

    物件名.屬性名 = 值
    • 類里面

    self.屬性名 = 值
  • 獲取物件屬性

    • 類外面

    物件名.屬性名
    • 類里面

    self.屬性名
  • 魔法方法

    • __init__(): 初始化

    • __str__():輸出物件資訊

    • __del__():洗掉物件時呼叫

面向物件-繼承

繼承的概念

生活中的繼承,一般指的是子女繼承父輩的財產,

  • 拓展1:經典類或舊式類

不由任意內置型別派生出的類,稱之為經典類,

class 類名:
    代碼
    ......
  • 拓展2:新式類

class 類名(object):
  代碼

Python面向物件的繼承指的是多個類之間的所屬關系,即子類默認繼承父類的所有屬性和方法,具體如下:

# 父類A
class A(object):
    def __init__(self):
        self.num = 1
?
    def info_print(self):
        print(self.num)
?
# 子類B
class B(A):
    pass
?
?
result = B()
result.info_print()  # 1

在Python中,所有類默認繼承object類,object類是頂級類或基類;其他子類叫做派生類,

單繼承

故事主線:一個煎餅果子老師傅,在煎餅果子界摸爬滾打多年,研發了一套精湛的攤煎餅果子的技術,師父要把這套技術傳授給他的唯一的最得意的徒弟,

分析:徒弟是不是要繼承師父的所有技術?

# 1. 師父類
class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎餅果子配方]'
?
    def make_cake(self):
        print(f'運用{self.kongfu}制作煎餅果子')
?
        
# 2. 徒弟類
class Prentice(Master):
    pass
?
?
# 3. 創建物件daqiu
daqiu = Prentice()
# 4. 物件訪問實體屬性
print(daqiu.kongfu)
# 5. 物件呼叫實體方法
daqiu.make_cake()

多繼承

故事推進:小明是個愛學習的好孩子,想學習更多的煎餅果子技術,于是,在百度搜索學習

所謂多繼承意思就是一個類同時繼承了多個父類,

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎餅果子配方]'
?
    def make_cake(self):
        print(f'運用{self.kongfu}制作煎餅果子')
?
?
# 創建學校類
class School(object):
    def __init__(self):
        self.kongfu = '[煎餅果子配方]'
?
    def make_cake(self):
        print(f'運用{self.kongfu}制作煎餅果子')
?
?
class Prentice(School, Master):
    pass
?
?
daqiu = Prentice()
print(daqiu.kongfu)
daqiu.make_cake()

注意:當一個類有多個父類的時候,默認使用第一個父類的同名屬性和方法,

子類重寫父類同名方法和屬性

故事:小明掌握了師父和培訓的技術后,自己潛心鉆研出自己的獨門配方的一套全新的煎餅果子技術,

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎餅果子配方]'
?
    def make_cake(self):
        print(f'運用{self.kongfu}制作煎餅果子')
?
?
class School(object):
    def __init__(self):
        self.kongfu = '[煎餅果子配方]'
?
    def make_cake(self):
        print(f'運用{self.kongfu}制作煎餅果子')
?
?
# 獨創配方
class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[獨創煎餅果子配方]'
?
    def make_cake(self):
        print(f'運用{self.kongfu}制作煎餅果子')
?
?
daqiu = Prentice()
print(daqiu.kongfu)
daqiu.make_cake()
?
print(Prentice.__mro__)

子類和父類具有同名屬性和方法,默認使用子類的同名屬性和方法,

子類呼叫父類的同名方法和屬性

故事:很多顧客都希望也能吃到古法和黑馬的技術的煎餅果子,

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎餅果子配方]'
?
    def make_cake(self):
        print(f'運用{self.kongfu}制作煎餅果子')
?
?
class School(object):
    def __init__(self):
        self.kongfu = '[黑馬煎餅果子配方]'
?
    def make_cake(self):
        print(f'運用{self.kongfu}制作煎餅果子')
?
?
class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[獨創煎餅果子配方]'
?
    def make_cake(self):
        # 如果是先呼叫了父類的屬性和方法,父類屬性會覆寫子類屬性,故在呼叫屬性前,先呼叫自己子類的初始化
        self.__init__()
        print(f'運用{self.kongfu}制作煎餅果子')
?
    # 呼叫父類方法,但是為保證呼叫到的也是父類的屬性,必須在呼叫方法前呼叫父類的初始化
    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)
?
    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)
?
?
daqiu = Prentice()
?
daqiu.make_cake()
?
daqiu.make_master_cake()
?
daqiu.make_school_cake()
?
daqiu.make_cake()

多層繼承

故事:N年后,小明老了,想要把所有技術傳承給自己的徒弟,

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎餅果子配方]'
?
    def make_cake(self):
        print(f'運用{self.kongfu}制作煎餅果子')
?
?
class School(object):
    def __init__(self):
        self.kongfu = '[煎餅果子配方]'
?
    def make_cake(self):
        print(f'運用{self.kongfu}制作煎餅果子')
?
?
class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[獨創煎餅果子配方]'
?
    def make_cake(self):
        self.__init__()
        print(f'運用{self.kongfu}制作煎餅果子')
?
    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)
?
    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)
?
?
# 徒孫類
class Tusun(Prentice):
    pass
?
?
xiaoqiu = Tusun()
?
xiaoqiu.make_cake()
?
xiaoqiu.make_school_cake()
?
xiaoqiu.make_master_cake()
?

super()呼叫父類方法

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎餅果子配方]'
?
    def make_cake(self):
        print(f'運用{self.kongfu}制作煎餅果子')
?
?
class School(Master):
    def __init__(self):
        self.kongfu = '[煎餅果子配方]'
?
    def make_cake(self):
        print(f'運用{self.kongfu}制作煎餅果子')
?
        # 方法2.1
        # super(School, self).__init__()
        # super(School, self).make_cake()
?
        # 方法2.2
        super().__init__()
        super().make_cake()
?
?
class Prentice(School):
    def __init__(self):
        self.kongfu = '[獨創煎餅果子技術]'
?
    def make_cake(self):
        self.__init__()
        print(f'運用{self.kongfu}制作煎餅果子')
?
    # 子類呼叫父類的同名方法和屬性:把父類的同名屬性和方法再次封裝
    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)
?
    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)
?
    # 一次性呼叫父類的同名屬性和方法
    def make_old_cake(self):
        # 方法一:代碼冗余;父類類名如果變化,這里代碼需要頻繁修改
        # Master.__init__(self)
        # Master.make_cake(self)
        # School.__init__(self)
        # School.make_cake(self)
?
        # 方法二: super()
        # 方法2.1 super(當前類名, self).函式()
        # super(Prentice, self).__init__()
        # super(Prentice, self).make_cake()
?
        # 方法2.2 super().函式()
        super().__init__()
        super().make_cake()
?
?
daqiu = Prentice()
?
daqiu.make_old_cake()

注意:使用super() 可以自動查找父類,呼叫順序遵循 __mro__ 類屬性的順序,比較適合單繼承使用,

私有權限

定義私有屬性和方法

在Python中,可以為實體屬性和方法設定私有權限,即設定某個實體屬性或實體方法不繼承給子類,

故事:小明把技術傳承給徒弟的同時,不想把自己的錢(2000000個億)繼承給徒弟,這個時候就要為這個實體屬性設定私有權限,

設定私有權限的方法:在屬性名和方法名 前面 加上兩個下劃線 __,

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎餅果子配方]'
?
    def make_cake(self):
        print(f'運用{self.kongfu}制作煎餅果子')
?
?
class School(object):
    def __init__(self):
        self.kongfu = '[煎餅果子配方]'
?
    def make_cake(self):
        print(f'運用{self.kongfu}制作煎餅果子')
?
?
class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[獨創煎餅果子配方]'
        # 定義私有屬性
        self.__money = 2000000
?
    # 定義私有方法
    def __info_print(self):
        print(self.kongfu)
        print(self.__money)
?
    def make_cake(self):
        self.__init__()
        print(f'運用{self.kongfu}制作煎餅果子')
?
    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)
?
    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)
?
?
# 徒孫類
class Tusun(Prentice):
    pass
?
?
daqiu = Prentice()
# 物件不能訪問私有屬性和私有方法
# print(daqiu.__money)
# daqiu.__info_print()
?
xiaoqiu = Tusun()
# 子類無法繼承父類的私有屬性和私有方法
# print(xiaoqiu.__money)  # 無法訪問實體屬性__money
# xiaoqiu.__info_print()

注意:私有屬性和私有方法只能在類里面訪問和修改,

獲取和修改私有屬性值

在Python中,一般定義函式名get_xx用來獲取私有屬性,定義set_xx用來修改私有屬性值,

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎餅果子配方]'
?
    def make_cake(self):
        print(f'運用{self.kongfu}制作煎餅果子')
?
?
class School(object):
    def __init__(self):
        self.kongfu = '[煎餅果子配方]'
?
    def make_cake(self):
        print(f'運用{self.kongfu}制作煎餅果子')
?
?
class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[獨創煎餅果子配方]'
        self.__money = 2000000
?
    # 獲取私有屬性
    def get_money(self):
        return self.__money
?
    # 修改私有屬性
    def set_money(self):
        self.__money = 500
?
    def __info_print(self):
        print(self.kongfu)
        print(self.__money)
?
    def make_cake(self):
        self.__init__()
        print(f'運用{self.kongfu}制作煎餅果子')
?
    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)
?
    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)
?
?
# 徒孫類
class Tusun(Prentice):
    pass
?
?
daqiu = Prentice()
?
xiaoqiu = Tusun()
# 呼叫get_money函式獲取私有屬性money的值
print(xiaoqiu.get_money())
# 呼叫set_money函式修改私有屬性money的值
xiaoqiu.set_money()
print(xiaoqiu.get_money())

總結

  • 繼承的特點

    • 子類默認擁有父類的所有屬性和方法

    • 子類重寫父類同名方法和屬性

    • 子類呼叫父類同名方法和屬性

  • super()方法快速呼叫父類方法

  • 私有權限

    • 不能繼承給子類的屬性和方法需要添加私有權限

    • 語法

    class 類名():
      # 私有屬性
      __屬性名 = 值
    ?
      # 私有方法
      def __函式名(self):
        代碼
    
    

面向物件-其他

面向物件三大特性

  • 封裝

    • 將屬性和方法書寫到類的里面的操作即為封裝

    • 封裝可以為屬性和方法添加私有權限

  • 繼承

    • 子類默認繼承父類的所有屬性和方法

    • 子類可以重寫父類屬性和方法

  • 多型

    • 傳入不同的物件,產生不同的結果

多型

了解多型

多型指的是一類事物有多種形態,(一個抽象類有多個子類,因而多型的概念依賴于繼承),

  • 定義:多型是一種使用物件的方式,子類重寫父類方法,呼叫不同子類物件的相同父類方法,可以產生不同的執行結果

  • 好處:呼叫靈活,有了多型,更容易撰寫出通用的代碼,做出通用的編程,以適應需求的不斷變化!

  • 實作步驟:

    • 定義父類,并提供公共方法

    • 定義子類,并重寫父類方法

    • 傳遞子類物件給呼叫者,可以看到不同子類執行效果不同

體驗多型

class Dog(object):
    def work(self):  # 父類提供統一的方法,哪怕是空方法
        print('指哪打哪...')
?
?
class ArmyDog(Dog):  # 繼承Dog類
    def work(self):  # 子類重寫父類同名方法
        print('追擊敵人...')
?
?
class DrugDog(Dog):
    def work(self):
        print('追查毒品...')
?
?
class Person(object):
    def work_with_dog(self, dog):  # 傳入不同的物件,執行不同的代碼,即不同的work函式
        dog.work()
?
?
ad = ArmyDog()
dd = DrugDog()
?
daqiu = Person()
daqiu.work_with_dog(ad)
daqiu.work_with_dog(dd)

類屬性和實體屬性

類屬性

設定和訪問類屬性

  • 類屬性就是 類物件 所擁有的屬性,它被 該類的所有實體物件 所共有

  • 類屬性可以使用 類物件實體物件 訪問,

class Dog(object):
    tooth = 10
?
?
wangcai = Dog()
xiaohei = Dog()
?
print(Dog.tooth)  # 10
print(wangcai.tooth)  # 10
print(xiaohei.tooth)  # 10

類屬性的優點

  • 記錄的某項資料 始終保持一致時,則定義類屬性,

  • 實體屬性 要求 每個物件 為其 單獨開辟一份記憶體空間 來記錄資料,而 類屬性 為全類所共有 ,僅占用一份記憶體更加節省記憶體空間

修改類屬性

類屬性只能通過類物件修改,不能通過實體物件修改,如果通過實體物件修改類屬性,表示的是創建了一個實體屬性,

class Dog(object):
    tooth = 10
?
?
wangcai = Dog()
xiaohei = Dog()
?
# 修改類屬性
Dog.tooth = 12
print(Dog.tooth)  # 12
print(wangcai.tooth)  # 12
print(xiaohei.tooth)  # 12
?
# 不能通過物件修改屬性,如果這樣操作,實則是創建了一個實體屬性
wangcai.tooth = 20
print(Dog.tooth)  # 12
print(wangcai.tooth)  # 20
print(xiaohei.tooth)  # 12

實體屬性

class Dog(object):
    def __init__(self):
        self.age = 5
?
    def info_print(self):
        print(self.age)
?
?
wangcai = Dog()
print(wangcai.age)  # 5
# print(Dog.age)  # 報錯:實體屬性不能通過類訪問
wangcai.info_print()  # 5

類方法和靜態方法

類方法

類方法特點

  • 需要用裝飾器@classmethod來標識其為類方法,對于類方法,第一個引數必須是類物件,一般以cls作為第一個引數,

類方法使用場景

  • 當方法中 需要使用類物件 (如訪問私有類屬性等)時,定義類方法

  • 類方法一般和類屬性配合使用

class Dog(object):
    __tooth = 10
?
    @classmethod
    def get_tooth(cls):
        return cls.__tooth
?
?
wangcai = Dog()
result = wangcai.get_tooth()
print(result)  # 10

靜態方法

靜態方法特點

  • 需要通過裝飾器@staticmethod來進行修飾,靜態方法既不需要傳遞類物件也不需要傳遞實體物件(形參沒有self/cls)

  • 靜態方法 也能夠通過 實體物件類物件 去訪問,

靜態方法使用場景

  • 當方法中 既不需要使用實體物件(如實體物件,實體屬性),也不需要使用類物件 (如類屬性、類方法、創建實體等)時,定義靜態方法

  • 取消不需要的引數傳遞,有利于 減少不必要的記憶體占用和性能消耗

class Dog(object):
    @staticmethod
    def info_print():
        print('這是一個狗類,用于創建狗實體....')
?
?
wangcai = Dog()
# 靜態方法既可以使用物件訪問又可以使用類訪問
wangcai.info_print()
Dog.info_print()

總結

  • 面向物件三大特性

    • 封裝

    • 繼承

    • 多型

  • 類屬性

    • 歸屬于類物件的屬性,所有物件共有的屬性

  • 實體屬性

  • 類方法

@classmethod
def xx():
  代碼
  • 靜態方法

@staticmethod
def xx():
  代碼

例外

了解例外

當檢測到一個錯誤時,解釋器就無法繼續執行了,反而出現了一些錯誤的提示,這就是所謂的"例外",

例如:以r方式打開一個不存在的檔案,

open('test.txt', 'r')

例外的寫法

語法

try:
    可能發生錯誤的代碼
except:
    如果出現例外執行的代碼

快速體驗

需求:嘗試以r模式打開檔案,如果檔案不存在,則以w方式打開,

try:
    f = open('test.txt', 'r')
except:
    f = open('test.txt', 'w')

捕獲指定例外

語法

try:
    可能發生錯誤的代碼
except 例外型別:
    如果捕獲到該例外型別執行的代碼

體驗

try:
    print(num)
except NameError:
    print('有錯誤')

注意:

  1. 如果嘗試執行的代碼的例外型別和要捕獲的例外型別不一致,則無法捕獲例外,

  2. 一般try下方只放一行嘗試執行的代碼,

捕獲多個指定例外

當捕獲多個例外時,可以把要捕獲的例外型別的名字,放到except 后,并使用元組的方式進行書寫,

try:
    print(1/0)
?
except (NameError, ZeroDivisionError):
    print('有錯誤')

捕獲例外描述資訊

try:
    print(num)
except (NameError, ZeroDivisionError) as result:
    print(result)

捕獲所有例外

Exception是所有程式例外類的父類,

try:
    print(num)
except Exception as result:
    print(result)

例外的else

else表示的是如果沒有例外要執行的代碼,

try:
    print(1)
except Exception as result:
    print(result)
else:
    print('我是else,是沒有例外的時候執行的代碼')

例外的finally

finally表示的是無論是否例外都要執行的代碼,例如關閉檔案,

try:
    f = open('test.txt', 'r')
except Exception as result:
    f = open('test.txt', 'w')
else:
    print('沒有例外,真開心')
finally:
    f.close()

例外的傳遞

體驗例外傳遞

需求:

1. 嘗試只讀方式打開test.txt檔案,如果檔案存在則讀取檔案內容,檔案不存在則提示用戶即可,

2. 讀取內容要求:嘗試回圈讀取內容,讀取程序中如果檢測到用戶意外終止程式,則except捕獲例外并提示用戶,

import time
try:
    f = open('test.txt')
    try:
        while True:
            content = f.readline()
            if len(content) == 0:
                break
            time.sleep(2)
            print(content)
    except:
        # 如果在讀取檔案的程序中,產生了例外,那么就會捕獲到
        # 比如 按下了 ctrl+c
        print('意外終止了讀取資料')
    finally:
        f.close()
        print('關閉檔案')
except:
    print("沒有這個檔案")

自定義例外

在Python中,拋出自定義例外的語法為raise 例外類物件

需求:密碼長度不足,則報例外(用戶輸入密碼,如果輸入的長度不足3位,則報錯,即拋出自定義例外,并捕獲該例外),

# 自定義例外類,繼承Exception
class ShortInputError(Exception):
    def __init__(self, length, min_len):
        self.length = length
        self.min_len = min_len
?
    # 設定拋出例外的描述資訊
    def __str__(self):
        return f'你輸入的長度是{self.length}, 不能少于{self.min_len}個字符'
?
?
def main():
    try:
        con = input('請輸入密碼:')
        if len(con) < 3:
            raise ShortInputError(len(con), 3)
    except Exception as result:
        print(result)
    else:
        print('密碼已經輸入完成')
?
?
main()

總結

  • 例外語法

try:
    可能發生例外的代碼
except:
    如果出現例外執行的代碼
else:
    沒有例外執行的代碼
finally:
    無論是否例外都要執行的代碼
  • 捕獲例外

except 例外型別:
    代碼
?
except 例外型別 as xx:
        代碼
  • 自定義例外

# 1. 自定義例外類
class 例外類類名(Exception):
    代碼
    
    # 設定拋出例外的描述資訊
    def __str__(self):
      return ...
?
?
# 2. 拋出例外
raise 例外類名()
?
# 捕獲例外
except Exception...

模塊和包

模塊

Python 模塊(Module),是一個 Python 檔案,以 .py 結尾,包含了 Python 物件定義和Python陳述句,

模塊能定義函式,類和變數,模塊里也能包含可執行的代碼,

匯入模塊

匯入模塊的方式

  • import 模塊名

  • from 模塊名 import 功能名

  • from 模塊名 import *

  • import 模塊名 as 別名

  • from 模塊名 import 功能名 as 別名

匯入方式詳解

import

  • 語法

# 1. 匯入模塊
import 模塊名
import 模塊名1, 模塊名2...
?
# 2. 呼叫功能
模塊名.功能名()
  • 體驗

import math
print(math.sqrt(9))  # 3.0

from..import..

  • 語法

from 模塊名 import 功能1, 功能2, 功能3...
  • 體驗

from math import sqrt
print(sqrt(9))

from .. import *

  • 語法

from 模塊名 import *
  • 體驗

from math import *
print(sqrt(9))

as定義別名

  • 語法

# 模塊定義別名
import 模塊名 as 別名
?
# 功能定義別名
from 模塊名 import 功能 as 別名
  • 體驗

# 模塊別名
import time as tt
?
tt.sleep(2)
print('hello')
?
# 功能別名
from time import sleep as sl
sl(2)
print('hello')

制作模塊

在Python中,每個Python檔案都可以作為一個模塊,模塊的名字就是檔案的名字,也就是說自定義模塊名必須要符合識別符號命名規則,

定義模塊

新建一個Python檔案,命名為my_module1.py,并定義testA函式,

def testA(a, b):
    print(a + b)

測驗模塊

在實際開中,當一個開發人員撰寫完一個模塊后,為了讓模塊能夠在專案中達到想要的效果,這個開發人員會自行在py檔案中添加一些測驗資訊.,例如,在my_module1.py檔案中添加測驗代碼,

def testA(a, b):
    print(a + b)
?
?
testA(1, 1)

此時,無論是當前檔案,還是其他已經匯入了該模塊的檔案,在運行的時候都會自動執行testA函式的呼叫,

解決辦法如下:

def testA(a, b):
    print(a + b)
?
# 只在當前檔案中呼叫該函式,其他匯入的檔案內不符合該條件,則不執行testA函式呼叫
if __name__ == '__main__':
    testA(1, 1)

呼叫模塊

import my_module1
my_module1.testA(1, 1)

注意事項

如果使用from .. import ..from .. import *匯入多個模塊的時候,且模塊內有同名功能,當呼叫這個同名功能的時候,呼叫到的是后面匯入的模塊的功能,

  • 體驗

# 模塊1代碼
def my_test(a, b):
    print(a + b)
?
# 模塊2代碼
def my_test(a, b):
    print(a - b)
   
# 匯入模塊和呼叫功能代碼
from my_module1 import my_test
from my_module2 import my_test
?
# my_test函式是模塊2中的函式
my_test(1, 1)

模塊定位順序

當匯入一個模塊,Python決議器對模塊位置的搜索順序是:

  1. 當前目錄

  2. 如果不在當前目錄,Python則搜索在shell變數PYTHONPATH下的每個目錄,

  3. 如果都找不到,Python會察看默認路徑,UNIX下,默認路徑一般為/usr/local/lib/python/

模塊搜索路徑存盤在system模塊的sys.path變數中,變數里包含當前目錄,PYTHONPATH和由安裝程序決定的默認目錄,

  • 注意

    • 自己的檔案名不要和已有模塊名重復,否則導致模塊功能無法使用

    • 使用from 模塊名 import 功能的時候,如果功能名字重復,呼叫到的是最后定義或匯入的功能,

__all__

如果一個模塊檔案中有__all__變數,當使用from xxx import *匯入時,只能匯入這個串列中的元素,

  • my_module1模塊代碼

__all__ = ['testA']
?
?
def testA():
    print('testA')
?
?
def testB():
    print('testB')
  • 匯入模塊的檔案代碼

from my_module1 import *
testA()
testB()

包將有聯系的模塊組織在一起,即放到同一個檔案夾下,并且在這個檔案夾創建一個名字為__init__.py 檔案,那么這個檔案夾就稱之為包,

制作包

[New] — [Python Package] — 輸入包名 — [OK] — 新建功能模塊(有聯系的模塊),

注意:新建包后,包內部會自動創建__init__.py檔案,這個檔案控制著包的匯入行為,

快速體驗

  1. 新建包mypackage

  2. 新建包內模塊:my_module1my_module2

  3. 模塊內代碼如下

# my_module1
print(1)
?
?
def info_print1():
    print('my_module1')
# my_module2
print(2)
?
?
def info_print2():
    print('my_module2')

匯入包

方法一

import 包名.模塊名
?
包名.模塊名.目標

體驗

import my_package.my_module1
?
my_package.my_module1.info_print1()

方法二

注意:必須在__init__.py檔案中添加__all__ = [],控制允許匯入的模塊串列,

from 包名 import *
模塊名.目標

體驗

from my_package import *
?
my_module1.info_print1()

總結

  • 匯入模塊方法

import 模塊名
?
from 模塊名 import 目標
?
from 模塊名 import *
  • 匯入包

import 包名.模塊名
?
from 包名 import *
  • __all__ = [] :允許匯入的模塊或功能串列

往期精彩:


我用Python修改了班花的開機密碼,重新登錄后竟然發現了她的秘密!

我用Python采集了班花的空間資料集,除了美照竟然再一次發現了她另外的秘密!

室友單戀班花失敗,我爬了一個網站發給他瞬間治愈,男人的快樂就這么簡單【每天一遍,忘記初戀】

Python學習傳送門

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/289592.html

標籤:python

上一篇:? Python入門 ? 2?? 寫一個溫度轉換小程式??

下一篇:Python基礎入門自學——18--操作Excel-作業實踐需求

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more