目錄
第0關(guān) print()函數(shù)與變量
第1關(guān) 數(shù)據(jù)類型與轉(zhuǎn)換
第2關(guān) 條件判斷與條件嵌套
第3關(guān) input()函數(shù)
第4關(guān) 列表和字典
第5關(guān) for循環(huán)和while循環(huán)
第6關(guān) 布爾值和四種語句
第7關(guān) 項(xiàng)目實(shí)操:PK小游戲(1)
第8關(guān) 編程思維:如何解決問題
第9關(guān) 函數(shù)
第10關(guān) 項(xiàng)目實(shí)操:PK小游戲(2)
第11關(guān) 編程思維:如何debug
第12關(guān) 類與對象1
第13關(guān) 類與對象2
第14關(guān) 項(xiàng)目實(shí)操:PK小游戲(3)
第15關(guān) 編碼和文件讀寫
第16關(guān) 模塊
第17關(guān) 項(xiàng)目實(shí)操:收發(fā)郵件
第18關(guān) 編程思維:產(chǎn)品思維
第19關(guān) 項(xiàng)目實(shí)操:畢業(yè)項(xiàng)目
1. print()函數(shù)print()
函數(shù):告訴計(jì)算機(jī),把括號的內(nèi)容顯示在屏幕上
# 不帶引號print(1+1) # 讓計(jì)算機(jī)讀懂括號里的內(nèi)容,打印最終的結(jié)果# 》》2# 帶引號print('hello world!') # 讓計(jì)算機(jī)無需理解,原樣復(fù)述引號中的內(nèi)容# 》》hello world!# 帶雙引號print("Let's play") # 讓計(jì)算機(jī)無需理解,原樣復(fù)述引號中的內(nèi)容,可以輸出內(nèi)容中的單引號# 》》Let's play# 三引號print(''' へ ?。瘄 /\7 ∠_/ / │ /?。? │ Z _,<?。 ?nbsp;/`ヽ │ ヽ / 〉 Y ` / / ?● ? ● ??〈 / () へ |?。堋? >? ?_ ?!?nbsp;│ // / へ / ?<| \\ ヽ_? (_/ │//''') # 原樣打印,實(shí)現(xiàn)換行# 》》 へ ?。瘄# /\7 ∠_/# / │ /?。? │ Z _,<?。 ?nbsp;/`ヽ# │ ヽ / 〉# Y ` / /# ?● ? ● ??〈 /# () へ |?。堋? >? ?_ ?!?nbsp;│ //# / へ / ?<| \\# ヽ_? (_/ │//
2. 轉(zhuǎn)義字符
=
表示,不要跟==搞混1. 數(shù)據(jù)類型
Python里,最常用的數(shù)據(jù)類型有三種——字符串(str)、整數(shù)(int)和浮點(diǎn)數(shù)(float)
· 字符串英文string,簡寫str,有層名為【引號】的皮,只要是被【單/雙/三引號】這層皮括起來的內(nèi)容,不論那個內(nèi)容是中文、英文、數(shù)字甚至火星文。只要是被括起來的,就表示是字符串類型
· 整數(shù)英文為integer,簡寫做int,Python世界的整數(shù)其實(shí)和現(xiàn)實(shí)世界數(shù)學(xué)中定義的一樣:是正整數(shù)、負(fù)整數(shù)和零的統(tǒng)稱,是沒有小數(shù)點(diǎn)的數(shù)字
· 浮點(diǎn)數(shù)的英文名是float,是帶小數(shù)點(diǎn)的數(shù)字。與【整數(shù)運(yùn)算結(jié)果永遠(yuǎn)精確】的特點(diǎn)不同,計(jì)算機(jī)里浮點(diǎn)數(shù)的運(yùn)算是不精確的,因?yàn)橛?jì)算浮點(diǎn)數(shù)時(shí)會先講數(shù)字轉(zhuǎn)換成二進(jìn)制數(shù),通過二進(jìn)制法則運(yùn)算后,再通過復(fù)雜的計(jì)算公式,將二進(jìn)制結(jié)果轉(zhuǎn)成十進(jìn)制小數(shù)
2. 算術(shù)運(yùn)算符
print(2+1) # 加法# 》》3print(1-2) # 減法# 》》-1print(1*2) # 乘法# 》》 2print(1/2) # 除法# 》》0.5print(5 % 2) # 取模(做除法返回余數(shù))# 》》1print(2**3) # 冪(這里是2的3次方)# 》》8print(11//2) # 取整除(做除法返回商的整數(shù)部分)# 》》5
type()
函數(shù)print(type('桂綸鎂'))# 》》<class 'str'>print(type(1))# 》》<class 'int'>print(type(1.55))# 》》<class 'float'>
4. 數(shù)據(jù)轉(zhuǎn)換
1. 條件判斷
name = input('請輸入你的名字:')# 將input()函數(shù)的執(zhí)行結(jié)果,在終端輸入的數(shù)據(jù),賦值給變量name
input()
函數(shù)的輸入值,永遠(yuǎn)會被【強(qiáng)制性】地轉(zhuǎn)換為【字符串】類型(Python3固定規(guī)則)
一些列表的相關(guān)操作↓
s = ['柯佳嬿', '許光漢', '施柏宇', '顏毓麟', '林鶴軒', '張翰']print(len(s)) # 打印列表s的長度# 》》6print(type(s)) # 打印列表s的類型# 》》<class 'list'>print(s[3]) # 打印列表s里面的第3個元素# 》》顏毓麟print(s[-3]) # 打印列表s里面的倒數(shù)第3個元素# 》》顏毓麟list1 = [91, 95, 97, 99] list2 = [92, 93, 96, 98]# 列表的合并list3 = list1+list2 # 第一種方法:+直接拼接print(list3)# 》》[91, 95, 97, 99, 92, 93, 96, 98]list1.extend(list2) # 第二種方法:extend()方法print(list1)# 》》[91, 95, 97, 99, 92, 93, 96, 98]# 列表的排序a = [91, 95, 97, 99, 92, 93, 96, 98] a.sort() # 列表從小到大排序print(a)# 》》[91, 92, 93, 95, 96, 97, 98, 99]b = [91, 95, 97, 99, 92, 93, 96, 98] b.sort(reverse=True) # 列表從大到小排序print(b)# 》》[99, 98, 97, 96, 95, 93, 92, 91]c = [91, 95, 97, 99, 92, 93, 96, 98] c.reverse() # 列表反向排序print(c)# 》》[98, 96, 93, 92, 99, 97, 95, 91]
用冒號來截取列表元素的操作叫作切片(slice),切片可以單拿出來說很長的篇幅,網(wǎng)上搜到一篇講的很清楚的:徹底搞懂Python切片操作
給列表增加元素:列表名.append()
給列表刪除元素:del 列表名[元素的索引]
pop()
函數(shù),用于移除列表中的一個元素(默認(rèn)最后一個元素),并且返回該元素的值↓
students = ['小明', '小紅', '小剛']for i in range(3): student1 = students.pop(0) # 運(yùn)用pop()函數(shù),同時(shí)完成提取和刪除。 students.append(student1) # 將移除的student1安排到最后一個座位。 print(students)# 》》》 ['小紅', '小剛', '小明']# 》》》 ['小剛', '小明', '小紅']# 》》》 ['小明', '小紅', '小剛']
2. 字典(dict)
字典中的鍵具備唯一性,而值可重復(fù)
從字典中提取元素:字典名[字典的鍵]
字典新增鍵值對:字典名[鍵] = 值
↓
scores = {'小明': 95, '小紅': 90, '小剛': 90}print(scores['小明']) # 從字典中提取元素# 》》95scores['小紅'] = 88 # 改變字典中的值print(scores['小紅'])# 》》88scores['小北'] = 98 # 給字典新增鍵和值print(scores)# 》》{'小明': 95, '小紅': 88, '小剛': 90, '小北': 98}
字典刪除鍵值對:del 字典名[鍵]
3. 列表和字典的不同點(diǎn)
列表中的元素是有自己明確的“位置”的,所以即使看似相同的元素,只要在列表所處的位置不同,它們就是兩個不同的列表。而字典相比起來就顯得隨和很多,調(diào)動順序也不影響。因?yàn)榱斜碇械臄?shù)據(jù)是有序排列的,而字典中的數(shù)據(jù)是隨機(jī)排列的。
4. 列表和字典的嵌套
students = { '第一組':['小明','小紅','小剛','小美'], '第二組':['小強(qiáng)','小蘭','小偉','小芳'] }print(students['第一組'][3])#取出'第一組'對應(yīng)列表偏移量為3的元素,即'小美'scores = [ {'小明':95,'小紅':90,'小剛':100,'小美':85}, {'小強(qiáng)':99,'小蘭':89,'小偉':93,'小芳':88} ]print(scores[1]['小強(qiáng)'])#先定位到列表偏移量為1的元素,即第二個字典,再取出字典里鍵為'小強(qiáng)'對應(yīng)的值,即99。
5. 元祖(tuple)
元組的寫法是將數(shù)據(jù)放在小括號()
中,它的用法和列表用法類似,主要區(qū)別在于列表中的元素可以隨時(shí)修改,但元組中的元素不可更改
list2 = [('A', 'B'), ('C', 'D'), ('E', 'F')]print(list2[1][1])# 》》 D# 從代碼里可看出:1.元組內(nèi)數(shù)據(jù)的提取也是用偏移量;2.元組也支持互相嵌套。
以上幾種關(guān)于收納的數(shù)據(jù)類型,最常用的還是列表,而對偏移量和切片的使用是寫算法非常重要的技能
1. for...in...循環(huán)語句
2. range()
函數(shù)
3. while循環(huán)
4. 兩種循環(huán)對比
布爾運(yùn)算的三種方式:
第一種計(jì)算:兩個數(shù)值做比較
一共有6種比較方式:==、!=、>、<、>=、<=
print(3 == 3.0)# 》》Trueprint('a' != 'a')# 》》Falseprint(3 > 5)# 》》Falseprint(3 < 5)# 》》Trueprint(100 >= 101)# 》》Falseprint(100 <= 101)# 》》True
第二種計(jì)算:直接用數(shù)值做運(yùn)算
第三種計(jì)算:布爾值之間的運(yùn)算
一共有5種計(jì)算方式:and、or、not、in、not in
# and計(jì)算和or計(jì)算a = 1b = -1print(a == 1 and b == 1) # and要求條件都滿足才為True# 》》Falseprint(a == 1 or b == 1) # or只要求其中一個條件滿足就為True# 》》True# not計(jì)算a = Trueprint(not a) # not計(jì)算會反轉(zhuǎn)真假# 》》False# in計(jì)算和not in計(jì)算a = [1, 2, 3, 4, 5]print(0 in a) # in用來判斷一個元素是否在一堆數(shù)據(jù)之中# 》》Falseprint(1 in a)# 》》Trueprint(0 not in a) # not in用來判斷一個元素是否不在一堆數(shù)據(jù)之中# 》》Trueprint(1 not in a)# 》》False
import time #調(diào)用time模塊time.sleep(secs) #使用time模塊下面的sleep()函數(shù),括號里填的是間隔的秒數(shù)(seconds,簡稱secs)#time.sleep(1.5)就表示停留1.5秒再運(yùn)行后續(xù)代碼
import random # 調(diào)用random模塊a = random.randint(1, 100)# 隨機(jī)生成1-100范圍內(nèi)(含1和100)的一個整數(shù),并賦值給變量aprint(a)print(random.choice([5, 7, 9, 11, 13, 15])) # 在給定列表中隨機(jī)選擇
取英文變量名推薦網(wǎng)站:CODELF三種格式化字符串方法↓
a = 5b = 7.85print(str(a)+'+'+str(b)+'='+str(a+b)) # 第一種:+拼接字符串和變量# 》》5+7.85=12.85print('%d+%s=%.2f' % (a, b, a+b)) # 第二種:格式符+類型碼 %.2f的意思是格式化字符串為浮點(diǎn)型并保留兩位小數(shù)# 》》5+7.85=12.85 print('{}+{}={}'.format(a, b, a+b)) # 第三種:format()函數(shù)# 》》5+7.85=12.85
拓展程序庫numpy
的簡單用法↓
import numpy as np # 導(dǎo)入 numpy庫,下面出現(xiàn)的 np 即 numpy庫a = [91, 95, 97, 99, 92, 93, 96, 98] average = np.mean(a) # 求平均數(shù),average是numpy.float64類型print(average)# 》》95.125b = np.array(a) # 將列表a轉(zhuǎn)換為numpy.ndarray類型print('小于平均數(shù)的有:{}' .format(b[b < average]))# 》》[91 95 92 93]c = b.tolist() # 將數(shù)組b轉(zhuǎn)換回列表print(type(c))# 》》<class 'list'>
函數(shù)是組織好的、可以重復(fù)使用的、用來實(shí)現(xiàn)單一功能的代碼
1. 定義和調(diào)用函數(shù)
# 函數(shù)名:1. 名字最好能體現(xiàn)函數(shù)的功能,一般用小寫字母和單下劃線、數(shù)字等組合# 2. 不可與內(nèi)置函數(shù)重名(內(nèi)置函數(shù)不需要定義即可直接使用)def math(x): # 參數(shù):根據(jù)函數(shù)功能,括號里可以有多個參數(shù),也可以不帶參數(shù),命名規(guī)則與函數(shù)名相同 # 規(guī)范:括號是英文括號,后面的冒號不能丟 y = x ** 2 + x# 函數(shù)體:函數(shù)的執(zhí)行過程,體現(xiàn)函數(shù)功能的語句,要縮進(jìn),一般是四個空格 return y# return語句:后面可以接多種數(shù)據(jù)類型,如果函數(shù)不需要返回值的話,可以省略print(math(5)) # 調(diào)用math()函數(shù)
2. 參數(shù)類型
以最熟悉的print()函數(shù)為例↓
print(*objects, sep = ' ', end = '\n', file = sys.stdout, flush = False)
可以看到第一個參數(shù)objects帶了*號,為不定長參數(shù)——這也是為什么print()函數(shù)可以傳遞任意數(shù)量的參數(shù)。其余四個為默認(rèn)參數(shù),我們可以通過修改默認(rèn)值來改變參數(shù)。
print('www', 'pypypy', 'cn') # objects -- 復(fù)數(shù),表示可以一次輸出多個對象。輸出多個對象時(shí),需要用 , 分隔。# 》》www pypypy cnprint('www', 'pypypy', 'cn', sep=".") # sep -- 用來間隔多個對象,默認(rèn)值是一個空格。# 》》www.pypypy.cnprint('hello', end='~~~~~~') # end -- 用來設(shè)定以什么結(jié)尾。默認(rèn)值是換行符 \n,可以換成其他字符串。print('world')# 》》hello~~~~~~world
print()函數(shù)的參數(shù)file和flush說起來篇幅比較長,單寫了篇關(guān)于print()、sys.stdout、sys.stderr的一些理解3. 返回多個值
def a(): return 1, 2, 3b = a() # 變量b接收函數(shù)a的返回值print(b) # 打印返回值# 》》(1, 2, 3)print(type(b)) # 打印返回值的類型# 》》<class 'tuple'>
也可以同時(shí)定義多個變量,來接收元組中的多個元素
def a(): return 1, 2, 3x, y, z = a()print(x)# 》》1print(y)# 》》2print(z)# 》》3
4. 變量作用域
· 一個在函數(shù)內(nèi)部賦值的變量僅能在該函數(shù)內(nèi)部使用(局部作用域),它們被稱作【局部變量】
· 在所有函數(shù)之外賦值的變量,可以在程序的任何位置使用(全局作用域),它們被稱作【全局變量】
如果想將局部變量聲明為全局變量,就要用到global
語句
tfc = 1000def tvc(): global tvc # global語句一般寫在函數(shù)體的第一行,它會告訴Python,“我希望tvc是個全局變量,所以請不要用這個名字創(chuàng)建一個局部變量” vc = 200 x = 10 tvc = vc * xdef tc(): print(tfc+tvc) # tc()函數(shù)內(nèi)部現(xiàn)在可以直接使用聲明后的全局變量tvctvc() tc()# 》》3000
5. 函數(shù)的嵌套
tfc = 1000def tvc(): vc = 200 x = 10 return vc * xdef tc(): print(tfc+tvc()) # 在tc()函數(shù)中調(diào)用了tvc()函數(shù)tc()# 》》3000
6. 遞歸
def digui(num): if (num == 1): return 1 return num * digui(num-1) x = digui(5)print(x)# 》》120
1. 向上取整
import math# 人力計(jì)算def estimated_number(size, time): number = size * 80 / time print(number) # 》》1.3333333333333333 print('項(xiàng)目大小為%.1f個標(biāo)準(zhǔn)項(xiàng)目,如果需要在%.1f個工時(shí)完成,則需要人力數(shù)量為:%d人' % (size, time, math.ceil(number))) # 通過ceil()函數(shù)向上取整 # 》》項(xiàng)目大小為1.0個標(biāo)準(zhǔn)項(xiàng)目,如果需要在60.0個工時(shí)完成,則需要人力數(shù)量為:2人estimated_number(1, 60)
如果不用ceil()
函數(shù),這個人力計(jì)算向上取整也可以通過判斷余數(shù)不為零就加一的方法實(shí)現(xiàn)
2. index()函數(shù)index()
函數(shù)用于找出列表中某個元素第一次出現(xiàn)的索引位置
import random punches = ['石頭', '剪刀', '布']# 猜拳游戲def punches_game(user_choice): computer_choice = random.choice(punches) if user_choice == computer_choice: print('平局') # 電腦的選擇有3種,索引位置分別是:0石頭、1剪刀、2布。 # 假設(shè)在電腦索引位置上減1,對應(yīng):-1布,0石頭,1剪刀,皆勝。 elif user_choice == punches[punches.index(computer_choice)-1]: print('你贏了') else: print('你輸了') punches_game(user_choice='布')
多行注釋有兩種快捷操作:1) 在需要注釋的多行代碼塊前后加一組三引號'''
2) 選中代碼后使用快捷鍵操作:Mac為cmd+/
異常處理:
= input(= input(= float(x)/(x, , y, % z, sep= ZeroDivisionError: ( ValueError: (
關(guān)于Python的所有報(bào)錯類型,一般可以在這里查閱:https://www.runoob.com/python/python-exceptions.html異常層次結(jié)構(gòu)需到官網(wǎng)查看https://docs.python.org/zh-cn/3/library/exceptions.html#exception-hierarchy
Python中的對象等于類(class)和實(shí)例(instance)的集合:即類可以看作是對象,實(shí)例也可以看作是對象
類名的首字母要大寫,以便讓我們輕松地辨認(rèn)出“哦!這個是類!”
實(shí)例方法的創(chuàng)建語句,和函數(shù)的定義語句很類似,唯一不同的是:實(shí)例方法中有個必須放在首位的參數(shù)self
class Computer: # 創(chuàng)建一個類 screen = True def start(self): print('電腦正在開機(jī)中……') my_computer = Computer() # 類的實(shí)例化print(type(my_computer)) # <class '__main__.Computer'>驗(yàn)證了my_computer屬于Computer這個類# 》》<class '__main__.Computer'>print(my_computer) # 打印出Computer類的一個實(shí)例對象(object),后面的一串字符表示這個對象的內(nèi)存地址(每次實(shí)例化都不一樣)# 》》<__main__.Computer object at 0x10e6bad00># 當(dāng)實(shí)例my_computer一被創(chuàng)建出來,就可以調(diào)用類中的屬性和方法。一句話概括就是:類有的實(shí)例都會有print(my_computer.screen) # 實(shí)例調(diào)用類屬性# 》》Truemy_computer.start() # 調(diào)用類中的方法(傳參不用管self)# 》》電腦正在開機(jī)中……
類中創(chuàng)建的屬性和方法可以被其所有的實(shí)例調(diào)用,而且,實(shí)例的數(shù)目在理論上是無限的。我們可以同時(shí)“新建”多個實(shí)例
因此,類也被稱為“實(shí)例工廠”,因其為所有實(shí)例提供了一套藍(lán)圖(即預(yù)先設(shè)定好有什么屬性和方法)
除了實(shí)例方法,還有兩個比較常見的方法類型,類方法和靜態(tài)方法
類方法需使用裝飾器@classmethod
,第一個參數(shù)必須是當(dāng)前類對象,該參數(shù)名一般約定為cls
,通過它來傳遞類的屬性和方法
class Computer: screen = '已開機(jī)' @classmethod def start(cls): print('電腦的狀態(tài)為:', cls.screen, sep='') Computer.start() # 可是是類對象調(diào)用# 》》電腦的狀態(tài)為:已開機(jī)my_computer = Computer() my_computer.start() # 也可以是實(shí)例對象調(diào)用# 》》電腦的狀態(tài)為:已開機(jī)
類方法是實(shí)例對象和類對象都可以調(diào)用,但實(shí)例方法只能由實(shí)例對象調(diào)用,如果非要用類調(diào)用,比如繼承重寫時(shí),那就把實(shí)例放在括號里傳參
靜態(tài)方法使用裝飾器@staticmethod
,參數(shù)隨意,實(shí)例對象和類對象都可以調(diào)用
如果只是存放邏輯性代碼,不涉及類中其他屬性或方法,就可以選擇使用靜態(tài)方法
import randomclass Computer: @staticmethod def start(): return random.randint(1, 99)print(Computer.start())
2. 特殊參數(shù):self
self會接收實(shí)例化過程中傳入的數(shù)據(jù),當(dāng)實(shí)例對象創(chuàng)建后,實(shí)例便會代替 self,在代碼中運(yùn)行。
class Chinese: name = '周冬雨' # 類屬性name def greeting(self): print('你好啊冬叔') def say(self): print(self.name + '是中國人') # 調(diào)用類屬性 self.greeting() # 調(diào)用實(shí)例方法person = Chinese() # 創(chuàng)建Chinese的實(shí)例personperson.say() # 調(diào)用實(shí)例方法# 》》周冬雨是中國人# 》》你好啊冬叔
當(dāng)最后一行代碼運(yùn)行時(shí),實(shí)例person會像參數(shù)一樣傳給self,替換掉self
作用相當(dāng)于:
class Chinese: name = '周冬雨' # 類屬性name def greeting(person): print('你好啊冬叔') def say(person): print(person.name + '是中國人') # 調(diào)用類屬性 person.greeting() # 調(diào)用實(shí)例方法person = Chinese() # 創(chuàng)建Chinese的實(shí)例personperson.say() # 調(diào)用實(shí)例方法# 》》周冬雨是中國人# 》》你好啊冬叔
self的作用相當(dāng)于先給實(shí)例占了個位置,關(guān)鍵在于占位,即使叫別的名字也是可以的,只是一般不這樣做而已
綜上,所以我們說self代表的是類的實(shí)例本身,方便數(shù)據(jù)的流轉(zhuǎn)。對此,需要記住兩點(diǎn):
第一點(diǎn):只要在類中用def創(chuàng)建實(shí)例方法時(shí),就必須把第一個參數(shù)位置留給self,并在調(diào)用方法時(shí)忽略它(不用給self傳參)
第二點(diǎn):當(dāng)在類的方法內(nèi)部想調(diào)用類屬性或其他方法時(shí),就要采用self.屬性名
或self.方法名
的格式
3. 特殊方法:初始化方法(也叫構(gòu)造函數(shù))
定義初始化方法的格式是def __init__(self)
,是由init加左右兩邊的【雙】下劃線組成( initialize “初始化”的縮寫)
初始化方法的作用在于:當(dāng)每個實(shí)例對象創(chuàng)建時(shí),該方法內(nèi)的代碼無須調(diào)用就會自動運(yùn)行
在編寫習(xí)慣上,我們會在初始化方法內(nèi)部完成類屬性的創(chuàng)建,為類屬性設(shè)置初始值,這樣類中的其他方法就能直接、隨時(shí)調(diào)用
class Chinese: def __init__(self, name, birth, region): self.name = name # self.name = '周冬雨' self.birth = birth # self.birth = '河北' self.region = region # self.region = '石家莊' def born(self): print(self.name + '出生在' + self.birth) def live(self): print(self.name + '居住在' + self.region) person = Chinese('周冬雨', '河北', '石家莊') # 傳入初始化方法的參數(shù)person.born()# 》》周冬雨出生在河北person.live()# 》》冬雨居住在石家莊
在Python中,我們的習(xí)慣表述是:A類是B類的子類,而B類是A類的父類(或超類)
類的定制,不僅可以讓子類擁有新的功能,還能讓它有權(quán)修改繼承到的代碼
所以,當(dāng)我們談定制時(shí),已經(jīng)包含了繼承。畢竟,類的定制的前提是繼承,而定制的加入讓類的繼承不僅僅只是單純的復(fù)制而已
1. 繼承的基礎(chǔ)語法
class Chinese: eye = 'black' def eat(self): print('吃飯,選擇用筷子')class Cantonese(Chinese): # 通過繼承,Chinese類有的,Cantonese類也有 pass# 驗(yàn)證子類可以繼承父類的屬性和方法,進(jìn)而傳遞給子類創(chuàng)建的實(shí)例yewen = Cantonese() # 子類創(chuàng)建的實(shí)例,從子類那間接得到了父類的所有屬性和方法print(yewen.eye) # 子類創(chuàng)建的實(shí)例,可調(diào)用父類的屬性# 》》blackyewen.eat() # 子類創(chuàng)建的實(shí)例,可調(diào)用父類的方法# 》》吃飯,選擇用筷子
函數(shù)isinstance()
,可以用來判斷某個實(shí)例是否屬于某個類
class Chinese: passclass Cantonese(Chinese): passgonger = Chinese() yewen = Cantonese()print(isinstance(yewen, Cantonese)) # 判斷yewen是否為Cantonese的實(shí)例# 》》Trueprint(isinstance(yewen, Chinese)) # 判斷yewen是否為Chinese的實(shí)例# 》》Trueprint(isinstance(gonger, Cantonese)) # 判斷gonger是否為Cantonese的實(shí)例# 》》Falseprint(isinstance(gonger, (Cantonese, Chinese))) # 判斷gonger實(shí)例是否屬于元組里幾個類中的一個# 》》Trueprint(isinstance(gonger, object)) # 判斷gonger是否為object的實(shí)例# 》》Trueprint(isinstance(yewen, object)) # 判斷yewen是否為object的實(shí)例# 》》True
理論上,父類可以被無限個子類所繼承
2. 類的繼承之多層繼承
子類創(chuàng)建的實(shí)例可調(diào)用所有層級父類的屬性和方法
class Earthman: eye_number = 2class Chinese(Earthman): eye_color = 'black'class Cantonese(Chinese): # Cantonese繼承了Chinese,同時(shí)也繼承了Earthman passyewen = Cantonese()print(yewen.eye_number)# 》》2print(yewen.eye_color)# 》》black
3. 類的繼承之多重繼承
一個類,可以同時(shí)繼承多個類,語法為class A(B,C,D):
括號里的順序是有講究的,和子類更相關(guān)的父類會放在更左側(cè),所以A的實(shí)例在調(diào)用屬性和方法時(shí),會先在左側(cè)的父類中找,找不到才會去右側(cè)的父類找(可理解為“就近原則”)
class Su: born_city = 'Jiangsu' wearing = 'thick' def diet(self): print('我們愛吃甜')class Yue: settle_city = 'Guangdong' wearing = 'thin' def diet(self): print('我們吃得清淡')class Yuesu(Yue, Su): passxiaoming = Yuesu()print(xiaoming.wearing) # 先在 Yue類找,找到了,打印出來# 》》thinprint(xiaoming.born_city) # Yue類沒有born_city,才去Su類找# 》》Jiangsuxiaoming.diet() # 方法調(diào)用,和屬性調(diào)用一樣,也符合就近原則# 》》我們吃得清淡
class C0: name = 'C0'class C2(C0): num = 2class C1: num = 1class C3: name = 'C3'class C4(C1, C2, C3): passins = C4()print(ins.name)# 》》C0print(ins.num)# 》》1
可以發(fā)現(xiàn)就近原則中的一個細(xì)節(jié):多重繼承中,若某父類還有父類的話,會先繼續(xù)往上找到頂
4. 類的定制,新增代碼
class Chinese: eye = 'black' def eat(self): print('吃飯,選擇用筷子')class Cantonese(Chinese): # 類的繼承 native_place = 'guangdong' # 類的定制 def dialect(self): # 類的定制 print('我們會講廣東話') yewen = Cantonese()print(yewen.eye) # 父類的屬性能用# 》》blackprint(yewen.native_place) # 子類的定制屬性也能用# 》》guangdongyewen.eat() # 父類的方法能用# 》》吃飯,選擇用筷子yewen.dialect() # 子類的定制方法也能用# 》》我們會講廣東話
可見:我們可以在子類下新建屬性或方法,讓子類可以用上父類所沒有的屬性或方法。這種操作,屬于定制中的一種:新增代碼
5. 類的定制,重寫代碼
重寫代碼,是在子類中,對父類代碼的修改
class Chinese: def land_area(self, area): print('我們居住的地方,陸地面積是%d萬平方公里左右' % area)class Cantonese(Chinese): def land_area(self, area, rate=0.0188): # 間接對方法進(jìn)行重寫 Chinese.land_area(self, area * rate) # 直接繼承父類方法,再調(diào)整參數(shù)gonger = Chinese() yewen = Cantonese() gonger.land_area(960)# 》》我們居住的地方,陸地面積是960萬平方公里左右yewen.land_area(960)# 》》我們居住的地方,陸地面積是18萬平方公里左右
子類繼承父類方法的操作是在def
語句后接父類.方法(參數(shù))
在Python中,如果方法名形式是左右?guī)щp下劃線的,那么就屬于特殊方法(如初始化方法),有著特殊的功能
如果在類中定義了__str__(self)
方法,那么當(dāng)使用print打印實(shí)例對象的時(shí)候,就會直接打印出在這個方法中return的數(shù)據(jù)
class Book: def __init__(self, name, author, comment, state=0): self.name = name self.author = author self.comment = comment self.state = state def __str__(self): if self.state == 0: status = '未借出' else: status = '已借出' return '名稱:《%s》 作者:%s 推薦語:%s\n狀態(tài):%s ' % (self.name, self.author, self.comment, status) book1 = Book('像自由一樣美麗', '林達(dá)', '你要用光明來定義黑暗,用黑暗來定義光明') # 傳入?yún)?shù),創(chuàng)建實(shí)例對象print(book1) # 直接打印對象即可,不能寫成print(book1.__str__())# 》》名稱:《像自由一樣美麗》 作者:林達(dá) 推薦語:你要用光明來定義黑暗,用黑暗來定義光明# 》》狀態(tài):未借出
1. 二進(jìn)制
二進(jìn)制轉(zhuǎn)十進(jìn)制,例如:(11010)2 = 1*24+1*23+0*22+1*21+0*20 = (26)10
兩個二進(jìn)制位可以表示22,十進(jìn)制的0,1,2,3,四種狀態(tài)
八個二進(jìn)制位可以表示28,也就是256種狀態(tài)
用來存放一位0或1,就是計(jì)算機(jī)里最小的存儲單位,叫做【位】,也叫【比特】(bit)。8個比特構(gòu)成一個【字節(jié)】(byte),這是計(jì)算機(jī)里最常用的單位
“流量”就是這么計(jì)算的↓
3. 編碼方案在當(dāng)前的使用情況
第0,計(jì)算機(jī)是有自己的工作區(qū)的,這個工作區(qū)被稱為“內(nèi)存”。數(shù)據(jù)在內(nèi)存當(dāng)中處理時(shí),使用的格式是Unicode,統(tǒng)一標(biāo)準(zhǔn)
在Python3當(dāng)中,程序處理輸入的字符串是默認(rèn)使用Unicode編碼的,所以什么語言都可以輸入
第1,數(shù)據(jù)在硬盤上存儲,或者是在網(wǎng)絡(luò)上傳輸時(shí),用的是UTF-8,因?yàn)楣?jié)省空間。不必操心如何轉(zhuǎn)換UTF-8和Unicode,當(dāng)點(diǎn)擊保存的時(shí)候,程序已經(jīng)“默默地”做好了編碼工作
第2,一些中文的文件和中文網(wǎng)站,還在使用GBK,和GB2312
4. encode()和decode()
編碼,即將人類語言轉(zhuǎn)換為計(jì)算機(jī)語言,就是【編碼】encode();反之,就是【解碼】decode()。它們的用法如下圖所表示↓
print('柯佳嬿'.encode('utf-8'))# 》》b'\xe6\x9f\xaf\xe4\xbd\xb3\xe5\xac\xbf'print('柯佳嬿'.encode('gbk'))# 》》b'\xbf\xc2\xbc\xd1\x8b\xf7'print(b'\xe6\x9f\xaf\xe4\xbd\xb3\xe5\xac\xbf'.decode('utf-8'))# 》》柯佳嬿print(b'\xbf\xc2\xbc\xd1\x8b\xf7'.decode('gbk'))# 》》柯佳嬿print(type(b'\xbf\xc2\xbc\xd1\x8b\xf7'))# 》》<class 'bytes'>
將人類語言編碼后得到的結(jié)果,最前面都有字母b,代表是bytes(字節(jié))類型的數(shù)據(jù);\x是分隔符,用來分隔一個字節(jié)和另一個字節(jié)
所謂的編碼,其實(shí)本質(zhì)就是把str(字符串)類型的數(shù)據(jù),利用不同的編碼表,轉(zhuǎn)換成bytes(字節(jié))類型的數(shù)據(jù)
將\x替換為%,就是網(wǎng)址中的搜索條件了,百度搜索“柯佳嬿”↓
https://www.baidu.com/s?wd=%bf%c2%bc%d1%8b%f7(gbk)
https://www.baidu.com/s?wd=%e6%9f%af%e4%bd%b3%e5%ac%bf(utf-8)
用decode()解碼的時(shí)候要注意,UTF-8編碼的字節(jié)就一定要用UTF-8的規(guī)則解碼,其他編碼同理,否則就會出現(xiàn)亂碼或者報(bào)錯的情況
print('K'.encode('ASCII'))# 》》b'K'
大寫字母K被編碼后還是K,但這兩個K對計(jì)算機(jī)來說意義是不同的,前者是字符串,采用系統(tǒng)默認(rèn)的Unicode編碼,占兩個字節(jié),后者則是bytes類型的數(shù)據(jù),只占一個字節(jié),這也驗(yàn)證了前面所說的編碼就是將str類型轉(zhuǎn)換成bytes類型
5. 讀寫文件
open()
函數(shù)的第一個參數(shù)是文件路徑,分為兩種:相對路徑和絕對路徑,絕對路徑就是最完整的路徑,相對路徑指的就是【相對于當(dāng)前文件夾】的路徑,也就是當(dāng)前編寫的這個py文件所放的文件夾路徑open('C:\\Users\\Ted\\Desktop\\test\\abc.txt')# 將'\'替換成'\\'open(r'C:\Users\Ted\Desktop\test\abc.txt')# 在路徑前加上字母r
第二個參數(shù)表示打開文件時(shí)的模式,這里是字符串 'r',表示 read,表示我們以讀的模式打開了這個文件
第三個參數(shù)encoding='utf-8',表示的是返回的數(shù)據(jù)采用何種編碼,一般采用utf-8或者gbk,注意這里是寫encoding而不是encode
打開文件file1之后,就可以用read()
函數(shù)進(jìn)行讀取的操作
關(guān)閉文件,使用的是close()
函數(shù)
為啥要關(guān)閉文件呢?原因有兩個:1.計(jì)算機(jī)能夠打開的文件數(shù)量是有限制的,open()過多而不close()的話,就不能再打開文件了。2.能保證寫入的內(nèi)容已經(jīng)在文件里被保存好了。
write()
函數(shù)寫入文本文件的是字符串類型# 普通寫法file1 = open('abc.txt', 'a') file1.write('張無忌') file1.close()# 使用with關(guān)鍵字的寫法with open('abc.txt', 'a') as file1: # with open('文件地址','讀寫模式') as 變量名: # 格式:冒號不能丟 file1.write('張無忌') # 格式:對文件的操作要縮進(jìn) # 格式:無需用close()關(guān)閉
6. readlines()和writelines()
file1 = open('scores.txt', 'r', encoding='utf-8') file_lines = file1.readlines() file1.close()print(file_lines)# 》》['羅恩 23 35 44\n', '哈利 60 77 68 88 90\n', '赫敏 97 99 89 91 95 99\n', '馬爾福 100 85 90']
函數(shù)readlines()
是“按行讀取”,readlines() 會從txt文件取得一個列表,列表中的每個字符串就是scores.txt中的每一行,而且每個字符串后面還有換行的\n符號
file1 = open('scores.txt', 'w', encoding='utf-8') file_lines = file1.writelines( ['羅恩 23 35 44\n', '哈利 60 77 68 88 90\n', '赫敏 97 99 89 91 95 99\n', '馬爾福 100 85 90']) file1.close()
write()的參數(shù)必須是一個字符串,而writelines()
的參數(shù)可以是序列也可以是字符串
7. split()split()
通過指定分隔符對字符串進(jìn)行切片
a = 'jjj kkk lll'print(a.split(' '))# 》》['jjj', 'kkk', 'lll']b = input('請輸入內(nèi)容').split(',')print(type(b))# 》》<class 'list'>
8. join()join()
函數(shù),是把字符串合并
a = ['c', 'a', 't'] b = ''print(b.join(a))# 》》catc = '-'print(c.join(a))# 》》c-a-t
join()的用法是str.join(sequence),str代表在這些字符串之中,要用什么字符串連接,上面兩個例子,一個是空字符串,一個是橫杠,sequence代表數(shù)據(jù)序列,在這里是列表a
在模塊中,我們不但可以直接存放變量,還能存放函數(shù),還能存放類
定義變量需要用賦值語句,封裝函數(shù)需要用def語句,封裝類需要用class語句,但封裝模塊不需要任何語句
之所以不用任何語句,是因?yàn)槊恳环輪为?dú)的Python代碼文件(后綴名是.py的文件)就是一個單獨(dú)的模塊
封裝模塊的目的也是為了把程序代碼和數(shù)據(jù)存放起來以便再次利用。如果封裝成類和函數(shù),主要還是便于自己調(diào)用,但封裝了模塊,不僅能自己使用,文件的方式也很容易共享給其他人使用
所以,使用模塊主要有兩種方式,一種是自己建立模塊并使用,另外一種是使用他人共享的模塊
1. import語句
使用import
語句導(dǎo)入一個模塊,最主要的目的并不是運(yùn)行模塊中的執(zhí)行語句,而是為了利用模塊中已經(jīng)封裝好的變量、函數(shù)、類
模塊.
的格式# 這是模塊test.pyprint('正在學(xué)習(xí)模塊...') a = '我是模塊中的變量a'def hi(): a = '我是函數(shù)里的變量a' print('函數(shù)“hi”已經(jīng)運(yùn)行!')class Go2: a = '我是類Go2中的變量a' def do2(self): print('類Go2中的函數(shù)“do2”已經(jīng)運(yùn)行!')
# 這是主程序main.pyimport test # 導(dǎo)入test模塊print(test.a) # 使用“模塊.變量”調(diào)用模塊中的變量test.hi() # 使用“模塊.函數(shù)()”調(diào)用模塊中的函數(shù)A = test.Go2() # 使用“變量 = 模塊.類()”實(shí)例化模塊中的類print(A.a) # 實(shí)例化后,不再需要“模塊.”A.do2() # 實(shí)例化后,不再需要“模塊.”
下面是主程序main.py的執(zhí)行結(jié)果↓
在學(xué)習(xí)模塊... 我是模塊中的變量a 函數(shù)“hi”已經(jīng)運(yùn)行! 我是類Go2中的變量a 類Go2中的函數(shù)“do2”已經(jīng)運(yùn)行!
當(dāng)然test.py這種為了組織代碼而封裝的模塊是最好不要出現(xiàn)print('正在學(xué)習(xí)模塊...')這種執(zhí)行語句,這里寫一下主要是為了體現(xiàn)什么時(shí)候需要模塊.
import語句還有一種用法是import…as…
,比如我們覺得import test太長,就可以用import test as t語句,意思是為“test”取個別名為“t”,上面的main.py文件可以寫成這樣↓
# 這是主程序main.pyimport test as tprint(t.a) t.hi() A = t.Go2()print(A.a) A.do2()
當(dāng)需要同時(shí)導(dǎo)入多個模塊時(shí),可以用逗號隔開。比如import a,b,c可以同時(shí)導(dǎo)入“a.py,b.py,c.py”三個文件
2. from … import … 語句from … import …
語句可以從模塊中導(dǎo)入一個指定的部分到當(dāng)前模塊,格式如下↓
當(dāng)需要從模塊中同時(shí)導(dǎo)入多個指定內(nèi)容,也可以用逗號隔開,寫成from xx模塊 import a,b,c的形式,上面的main.py文件也可以寫成這樣↓
# 這是主程序main.pyfrom test import afrom test import hi, Go2print(a) # 打印變量“a”hi() # 調(diào)用函數(shù)“hi”A = Go2() # 實(shí)例化“Go2”類print(A.a) # 打印實(shí)例屬性“a”A.do2() # 調(diào)用實(shí)例方法“do2”
對于from … import …語句要注意的是,沒有被寫在import后面的內(nèi)容,將不會被導(dǎo)入
當(dāng)需要從模塊中指定所有內(nèi)容直接使用時(shí),可以寫成【from xx模塊 import *】的形式,*代表“模塊中所有的變量、函數(shù)、類”
不過一般情況下,不要為了圖方便直接使用【from xx模塊 import *】的形式
這是因?yàn)椋K.xx的調(diào)用形式能通過閱讀代碼一眼看出是在調(diào)用模塊中的變量/函數(shù)/方法,而去掉模塊.后代碼就不是那么直觀了
3. if __name__ == '__main__'
對于Python和其他許多編程語言來說,程序都要有一個運(yùn)行入口
在Python中,當(dāng)在運(yùn)行某一個py文件,就能啟動程序 ——— 這個py文件就是程序的運(yùn)行入口,例如剛才的main.py就是運(yùn)行入口
更復(fù)雜的情況,也可以運(yùn)行一個主模塊,然后層層導(dǎo)入其他模塊
當(dāng)有了一大堆py文件組成一個程序的時(shí)候,為了【指明】某個py文件是程序的運(yùn)行入口,可以在該py文件中寫出這樣的代碼
# 【文件:xx.py】代碼塊 ①……if __name__ == '__main__': 代碼塊 ②……
這句話的意思是這樣的↓
if __name__ == '__main__'
就相當(dāng)于是 Python 模擬的程序入口。Python 本身并沒有規(guī)定這么寫,這是一種程序員達(dá)成共識的編碼習(xí)慣random
模塊的關(guān)鍵知識(也就是比較有用的函數(shù)和類方法),可以做成這樣的筆記↓import random # 調(diào)用random模塊a = random.random() # 隨機(jī)從0-1之間(包括0不包括1)抽取一個小數(shù)print(a) a = random.randint(0, 100) # 隨機(jī)從0-100(包括0和100)之間抽取一個數(shù)字print(a) a = random.choice('abcdefg') # 隨機(jī)從字符串,列表等對象中抽取一個元素(可能會重復(fù))print(a) a = random.sample('abcdefg', 3) # 隨機(jī)從字符串,列表等對象中抽取多個不重復(fù)的元素print(a) items = [1, 2, 3, 4, 5, 6] # “隨機(jī)洗牌”,比如打亂列表random.shuffle(items)print(items)
可以使用dir()
函數(shù)查看一個模塊,看看它里面有什么變量、函數(shù)、類、類方法
import random # 調(diào)用random模塊print(dir(random))# 》》['BPF', 'LOG4', 'NV_MAGICCONST', 'RECIP_BPF', 'Random', 'SG_MAGICCONST', 'SystemRandom', 'TWOPI', '_Sequence', '_Set', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_accumulate', '_acos', '_bisect', '_ceil', '_cos', '_e', '_exp', '_inst', '_log', '_os', '_pi', '_random', '_repeat', '_sha512', '_sin', '_sqrt', '_test', '_test_generator', '_urandom', '_warn', 'betavariate', 'choice', 'choices', 'expovariate', 'gammavariate', 'gauss', 'getrandbits', 'getstate', 'lognormvariate', 'normalvariate', 'paretovariate', 'randint', 'random', 'randrange', 'sample', 'seed', 'setstate', 'shuffle', 'triangular', 'uniform', 'vonmisesvariate', 'weibullvariate']
這樣可以把模塊中的函數(shù)(函數(shù)和類方法)一覽無余地暴露出來。對于查到的結(jié)果"__xx__"結(jié)構(gòu)的(如__doc__),它們是系統(tǒng)相關(guān)的函數(shù),我們不用理會,直接看全英文的函數(shù)名即可
dir(x),可以查詢到x相關(guān)的函數(shù),x可以是模塊,也可以是任意一種對象
a = '' # 設(shè)置一個字符串print(dir(a)) # 把字符串相關(guān)的函數(shù)展示出來# 》》['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']a = [] # 設(shè)置一個列表print(dir(a)) # 把列表相關(guān)的函數(shù)展示出來# 》》['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']a = {} # 設(shè)置一個字典print(dir(a)) # 把字典相關(guān)的函數(shù)展示出來# 》》['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
數(shù)據(jù)分析需要用到pandas和NumPy模塊,網(wǎng)頁開發(fā)要用到Django模塊
5. csv模塊csv
是一種文件格式,你可以把它理解成“簡易版excel”。學(xué)會了csv模塊,就可以用程序處理簡單的電子表格了
csv模塊的中英文文檔:https://yiyibooks.cn/xx/python_352/library/csv.html#module-csv
新建了一個名為test.csv的文件,里面的內(nèi)容是這樣↓
csv讀取數(shù)據(jù)↓
import csv# 參數(shù)encoding='utf-8'防止出現(xiàn)亂碼with open('test.csv', newline='', encoding='utf-8') as f: # 使用csv的reader()方法,創(chuàng)建一個reader對象 reader = csv.reader(f) # 遍歷reader對象的每一行 for row in reader: print(row)# 》》['商品編號', '商品名稱', '單價(jià)', '庫存', '銷量']# 》》['1', '貓零食', '12', '3133', '5164']# 》》['2', '普通貓糧', '33', '5055', '2231']# 》》['3', '貓糧四合一', '187', '212', '334']
終端輸出的每一行信息都是一個列表
csv寫入數(shù)據(jù)
import csv with open('test.csv', 'a', newline='', encoding='utf-8') as f: writer = csv.writer(f) writer.writerow(['4', '貓砂', '25', '1022', '886']) writer.writerow(['5', '貓罐頭', '18', '2234', '3121'])
6. time模塊
import time# 開始計(jì)時(shí)start = time.time()# 格式化當(dāng)前日期和時(shí)間print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))# 倒計(jì)時(shí),第一種寫法for t in range(5, 0, -1): print('\r倒計(jì)時(shí) ' + str(t) + ' 秒', end='', flush=True) time.sleep(1)print('')# 倒計(jì)時(shí),第二種寫法for t in range(5, 0, -1): info = '倒計(jì)時(shí) ' + str(t) + ' 秒' print(info, end='') print('\b'*(len(info)*2), end='', flush=True) time.sleep(1)print('')# 結(jié)束計(jì)時(shí)end = time.time()print('開始時(shí)間:', end='')# 格式化開始時(shí)間print(time.strftime('%H:%M:%S', time.localtime(start)))print('結(jié)束時(shí)間:', end='')# 格式化結(jié)束時(shí)間print(time.strftime('%H:%M:%S', time.localtime(end)))# 計(jì)算持續(xù)時(shí)間print('持續(xù)了%d秒' % (end-start))
執(zhí)行后顯示效果↓
import os# 讀取本地文件test.txt的內(nèi)容并賦值給變量awith open('test.txt', 'r') as f: a = f.read()# 在a的基礎(chǔ)上添加內(nèi)容并寫入到test_new.txtwith open('test_new.txt', 'w') as new: new.write(a+'Bewear')# 將test_new.txt重命名為test.txt,將其替代os.replace('test_new.txt', 'test.txt')# os.getcwd() # 返回當(dāng)前工作目錄# os.listdir(path) # 返回path指定的文件夾包含的文件或文件夾的名字的列表# os.mkdir(path) # 創(chuàng)建文件夾# os.path.abspath(path) # 返回絕對路徑# os.path.basename(path) # 返回文件名# os.path.isfile(path) # 判斷路徑是否為文件# os.path.isdir(path) # 判斷路徑是否為目錄
smtplib
模塊的以下方法↓import smtplib server = smtplib.SMTP() server.connect(host, port) server.login(username, password) server.sendmail(sender, to_addr, msg.as_string()) server.quit()
SMTP
(Simple Mail Transfer Protocol)代表“簡單郵件傳輸協(xié)議”,SMTP 協(xié)議是由源服務(wù)器到目的地服務(wù)器傳送郵件的一組規(guī)則
可以簡單理解為:需要通過SMTP指定一個服務(wù)器,這樣才能把郵件送到另一個服務(wù)器smtplib.SMTP.connect(host,port)
就是在連接指定的服務(wù)器
host是指定連接的郵箱服務(wù)器,可以指定服務(wù)器的域名;port 是“端口”,一般情況下SMTP默認(rèn)端口號為25。這兩個參數(shù)都可以到郵箱設(shè)置中找到
以QQ郵箱為例,SMTP服務(wù)器地址是:smtp.qq.com,端口是465或587
import smtplib server = smtplib.SMTP() server.connect('smtp.qq.com', 25)
二是嘗試設(shè)置中的端口,比如465。這時(shí)會有些不同,QQ 郵箱采用的加密方式是SSL,需要寫成這樣↓
import smtplib server = smtplib.SMTP_SSL()# 如果端口是用SSL加密,需要這樣寫server.connect('smtp.qq.com', 465)# 如果出現(xiàn)編碼錯誤UnicodeDecodeError,可以這樣寫:server.connect('smtp.qq.com', 465,'utf-8')
然后就要登錄郵箱了,login()
方法需要輸入兩個參數(shù):登錄郵箱和授權(quán)碼
username = 'xxx@qq.com'password = '你的授權(quán)碼數(shù)字'server.login(username, password)# username:登錄郵箱的用戶名# password:登錄密碼/授權(quán)碼
這個授權(quán)碼需要到這里獲取:打開https://mail.qq.com/,登錄郵箱,然后點(diǎn)擊位于頂部的【設(shè)置】按鈕,選擇【賬戶設(shè)置】,然后下拉到這個位置↓
接著是發(fā)送郵件,sendmail()
方法需要三個參數(shù):發(fā)件人,收件人和郵件內(nèi)容
這里的發(fā)件人from_addr與上面的username是一樣的,都是登錄郵箱,所以只用設(shè)置一次
server.sendmail(from_addr, to_addr, msg.as_string())# from_addr:郵件發(fā)送地址,就是上面的username# to_addr:郵件收件人地址# msg.as_string():為一個字符串類型
msg.as_string()是一個字符串類型:as_string()是將發(fā)送的信息msg變?yōu)樽址愋?nbsp;
msg就需要用到email模塊了,之后說
最后是quit()
退出服務(wù)器
server.quit()# 退出服務(wù)器,結(jié)束SMTP會話
2. email模塊email
模塊是用來寫郵件內(nèi)容的模塊。這個內(nèi)容可以是純文本、HTML內(nèi)容、圖片、附件等多種形式
from email.mime.text import MIMETextfrom email.mime.image import MIMEImagefrom email.mime.multipart import MIMEMultipart?
按住command同時(shí)點(diǎn)擊mime,會看到一個名為__init__.py的空文件,這說明email其實(shí)是一個“包”
模塊(module)一般是一個文件,而包(package)是一個目錄,一個包中可以包含很多個模塊,可以說包是“模塊打包”組成的
Python中的包都必須默認(rèn)包含一個__init__.py的文件
__init__.py控制著包的導(dǎo)入行為,假如這個文件為空,那么僅僅導(dǎo)入包的話,就什么都做不了,所以直接import email是行不通的,需要使用from … import …語句,從email包目錄下的【某個文件】引入【需要的對象】
關(guān)于模塊和包的概念可以看下這篇文章:https://www.cnblogs.com/ymjyqsx/p/6560210.html還是以QQ郵箱為例發(fā)送一封純文本郵件,除了引入了MIMEText
,還要引入為了構(gòu)建郵件頭的Header
建議代碼結(jié)構(gòu):①導(dǎo)入模塊 ②定義變量 ③使用方法
# smtplib 用于郵件的發(fā)信動作import smtplib# email 用于構(gòu)建郵件內(nèi)容from email.mime.text import MIMEText# 用于構(gòu)建郵件頭from email.header import Header# 發(fā)信方的信息:發(fā)信郵箱,QQ郵箱授權(quán)碼from_addr = 'xxx@qq.com'password = '授權(quán)碼數(shù)字'# 收信方郵箱to_addr = 'xxx@qq.com'# 發(fā)信服務(wù)器smtp_server = 'smtp.qq.com'# 郵件正文內(nèi)容text = '''寒蟬凄切,對長亭晚,驟雨初歇 都門帳飲無緒,留戀處,蘭舟催發(fā) 執(zhí)手相看淚眼,竟無語凝噎 念去去,千里煙波,暮靄沉沉楚天闊 多情自古傷離別,更那堪,冷落清秋節(jié) 今宵酒醒何處?楊柳岸,曉風(fēng)殘?jiān)? 此去經(jīng)年,應(yīng)是良辰好景虛設(shè) 便縱有千種風(fēng)情,更與何人說? 柳永 《雨霖鈴·寒蟬凄切》'''# 實(shí)例化一個MIMEText郵件對象,第一個參數(shù)為正文內(nèi)容,第二個參數(shù)為文本格式(plain為純文本),第三個參數(shù)為編碼msg = MIMEText(text, 'plain', 'utf-8')# 郵件頭信息msg['From'] = Header(from_addr) msg['To'] = Header(to_addr) msg['Subject'] = Header('python測試', 'utf-8')# 開啟發(fā)信服務(wù),這里使用的是加密傳輸server = smtplib.SMTP_SSL() server.connect(smtp_server, 465)# 登錄發(fā)信郵箱server.login(from_addr, password)# 發(fā)送郵件try: server.sendmail(from_addr, to_addr, msg.as_string()) print('恭喜,發(fā)送成功')except: print('發(fā)送失敗,請重試')# 關(guān)閉服務(wù)器server.quit()
郵件頭信息的寫法比較特殊,以msg['Subject'] = Header('python測試', 'utf-8')這句來說
等號右邊是實(shí)例化了一個Header郵件頭對象,該對象需要寫入兩個參數(shù),分別是郵件主題和編碼
等號左邊的msg['Subject']的變量是一個a['b']的代碼形式,它長得特別像字典根據(jù)鍵取值的表達(dá),但是這里的msg是一個MIMEText類的對象,并不是一個字典
其實(shí),字典和類在結(jié)構(gòu)上,有相似之處↓
# 改動這句代碼server = smtplib.SMTP_SSL()# 在括號內(nèi)加入host參數(shù)server = smtplib.SMTP_SSL(smtp_server)
如果用的是QQ以外的其他郵箱,比如企業(yè)郵箱的話,可能會出現(xiàn)報(bào)錯信息:smtplib.SMTPException: No suitable authentication method found
解決方案是在登錄(login)之前調(diào)用starttls()
方法就可以了
server.starttls()
還有些報(bào)錯實(shí)在搞不清楚是什么問題的話,可以嘗試將端口參數(shù)改一下,使用默認(rèn)端口25
# 把這兩行代碼改掉server = smtplib.SMTP_SSL() server.connect(smtp_server, 465)# 改掉port參數(shù),并去掉_SSLserver = smtplib.SMTP() server.connect(smtp_server, 25)
4. 群發(fā)郵件
將收件人信箱的變量設(shè)置成一個可以裝多個內(nèi)容的列表↓
to_addrs = ['xxx@qq.com', 'xxxxx@qq.com']
需要注意的是,Header接受的第一個參數(shù)的數(shù)據(jù)類型必須要是字符串或者字節(jié),所以在為msg['To']賦值的時(shí)候,需要將to_addrs轉(zhuǎn)換為字符串↓
msg['to'] = Header(",".join(to_addrs))
其他地方用到變量to_addr的地方替換成to_addrs就可以了
5. 制作二維碼-MyQR
第三方庫首先需要安裝,mac電腦在終端輸入pip3 install myqr
· 普通二維碼
from MyQR import myqr# 掃描二維碼后,顯示的內(nèi)容或是跳轉(zhuǎn)的鏈接myqr.run(words='https://www.cnblogs.com/oyster25')
在當(dāng)前目錄會生成一個叫qrcode.png的圖片,就是我們要的二維碼了
· 藝術(shù)二維碼
在當(dāng)前目錄有一張名為lm.jpg的圖片
from MyQR import myqr myqr.run( words='https://www.cnblogs.com/oyster25', picture='lm.jpg', # 將QR二維碼圖像與圖片相結(jié)合 colorized=True # 黑白(False)還是彩色(True),默認(rèn)是False)
這時(shí)會生成名為lm_qrcode.png的二維碼
· 動態(tài)二維碼
當(dāng)前目錄的lm.gif圖片
from MyQR import myqr myqr.run( words='https://www.cnblogs.com/oyster25', picture='lm.gif', colorized=True )
會生成一個叫l(wèi)m_qrcode.gif的動態(tài)二維碼myqr.run()
還有一些其他的參數(shù)↓
from MyQR import myqrimport os myqr.run( words='https://www.cnblogs.com/oyster25', # 掃描二維碼后,顯示的內(nèi)容或是跳轉(zhuǎn)的鏈接 version=10, # 設(shè)置容錯率,范圍是1-40 level='H', # 控制糾錯水平,范圍是L、M、Q、H,從左到右依次升高,默認(rèn)為H picture='lm.gif', # 將QR二維碼圖像與圖片相結(jié)合 colorized=True, # 黑白(False)還是彩色(True),默認(rèn)是False contrast=1.0, # 用以調(diào)節(jié)圖片的對比度,1.0 表示原始圖片。默認(rèn)為1.0 brightness=1.0, # 用來調(diào)節(jié)圖片的亮度,用法同上。 save_name='Python.gif', # 控制輸出文件名,格式可以是 .jpg, .png ,.bmp ,.gif,默認(rèn)輸出文件名qrcode.png或xx_qrcode.png(或.gif) save_dir=os.getcwd() # 控制存儲位置,默認(rèn)是當(dāng)前目錄)
由于將容錯率version調(diào)高了,所以生成的會慢一些;然后改了輸出的文件名,會生成一個叫Python.gif的動態(tài)二維碼
6. 絕對值abs()和math.fabs()
import math# 內(nèi)置模塊 math 求絕對值print(math.fabs(-1.32))# 》》1.32# 內(nèi)置函數(shù) abs() 求絕對值print(abs(-9))# 》》9
1. 流程圖
所有的流程圖,總結(jié)起來有三種類型↓
import os, timedef main(): content = '歡迎光臨穿著熊快餐車,喵喵喵~' for i in range(16): os.system('clear') print(content) content = content[1:]+content[0] time.sleep(0.25)if __name__ == '__main__': # 也可以直接用在函數(shù)上 main()
方法二↓
import time content = '歡迎光臨穿著熊快餐車,喵喵喵~'for i in range(16): print('\r'+content, end='', flush=True) content = content[1:]+content[0] time.sleep(0.25)print('')
一些遍歷字典的方法↓
tv_dict = {'芒果臺': '湖南衛(wèi)視', '荔枝臺': '江蘇衛(wèi)視', '番茄臺': '東方衛(wèi)視'}# 直接遍歷是取字典的鍵for tv in tv_dict: print(tv, end=' ')print('')# 》》芒果臺 荔枝臺 番茄臺# 遍歷字典取值for value in tv_dict.values(): print(value, end=' ')print('')# 》》南衛(wèi)視 江蘇衛(wèi)視 東方衛(wèi)視# 遍歷字典取鍵值對for logo, name in tv_dict.items(): print(logo + '是' + name)# 》》芒果臺是湖南衛(wèi)視# 》》荔枝臺是江蘇衛(wèi)視# 》》番茄臺是東方衛(wèi)視