文章目錄
- 語法基礎
- 判斷陳述句和回圈陳述句
- 串列
- 元組
- 字典
- 拆包
- 函式
- 檔案操作
- 面向物件基礎
- 例外
- 模塊
語法基礎
- 注釋
- 單行注釋 #
- 多行注釋 “"" xxx “”"
- 變數型別
type(V_name) 查看變數型別
不同的變數型別,占用的記憶體大小不同- Numbers
- 整形 int
- 長整型 long
- 浮點型 float
- 復數 complex
- 布爾型 bool
- 字串 str
- 串列 List
- 元組 Tuple
- 字典 Dictionary
- Numbers
- 識別符號
由字母,下劃線和數字組成,且數字不能開頭
區分大小寫 - 關鍵詞
特殊功能的識別符號
‘False’, ‘None’, ‘True’, ‘__peg_parser__’, ‘and’, ‘as’, ‘assert’, ‘async’, ‘await’, ‘break’, ‘class’, ‘continue’, ‘def’, ‘del’, ‘elif’, ‘else’, ‘except’, ‘finally’, ‘for’, ‘from’, ‘global’, ‘if’, ‘import’, ‘in’, ‘is’, ‘lambda’, ‘nonlocal’, ‘not’, ‘or’, ‘pass’, ‘raise’, ‘return’, ‘try’, ‘while’, ‘with’, ‘yield’
- 輸出
- 格式化輸出
格式化常用符號- %s 格式化字串
- %d 格式化整數
- %-2d 顯示兩位并左對齊,若只有一位則用空格占位,默認右對齊
- %f 格式化浮點數字,可指定小數點后的精度
myAge = 20 print("我的年齡是%d歲" % myAge)- 轉義輸出
常用轉義字符- \n 換行符
- \t 橫向制表符(TAB)
- \0 表示一個空字符
- \v 縱向制表符
- \r 回車符
- \f 換頁符
- 格式化輸出
- 輸入
input得到的結果是String
myName = input("please enter your Name:")
myAge = input("please enter your Age:")
print("Name:%s Age:%s" % (myName,myAge))
-
運算子
- 算術運算子
+ 加;- 減;* 乘;/ 除;// 整除;% 取余;** 指數 - 賦值運算子 =
- 復合賦值運算子
算術運算子復合賦值運算子 - 關系運算子
==;!=;>;<;>=;<= - 邏輯運算子
and;or;not
- 算術運算子
-
常用資料型別轉換
- int(x) 將x轉換為一個整數
- float(x) 將x轉換為一個浮點數
- str(x) 將x轉換為一個字串
- eval(str) 用來計算在字串中的有效python運算式,并回傳一個物件
判斷陳述句和回圈陳述句
- if-elif-else
if 判斷條件1:
執行陳述句1
elif 判斷條件2:
執行陳述句2
else:
執行陳述句3
- if嵌套(采用縮進區分層次)
money = eval(input("請輸入您公交卡的余額:"))
flag = not True
if money >= 2:
print("可以上公交車")
if flag:
print("可以坐下")
else:
print("站一會")
else:
print("請充值后再上車")
- while回圈
while 判斷條件:
執行陳述句
回圈標識+1
- while回圈嵌套
#九九乘法表
x = 1
while x <= 9:
# 定義一個變數 記錄列數
y = 1
while y <= x:
print("%d * %d = %-2d" % (y, x, x * y), end=" ")
y += 1
# 換行
print()
x += 1
- for回圈
范圍函式range()
range(m,n) -> [m,n)
range(n) -> [0,n)
for 臨時變數 in 可迭代物件(串列/字串/...):
執行陳述句
- break&continue
break:結束所有回圈
continue:提前結束本次回圈,進入下一次回圈 - for-else&while-else
for i in range(5):
print(i)
if i == 2:
#break
else:
print("else")
# while回圈
i = 0
while i < 5:
print(i)
if i == 2:
break
i += 1
else:
print("else")
"""
無論for-else 還是 while-else 如果在for回圈中 或者 while回圈中 沒有執行break 待for回圈或者while結束后 會執行else中的代碼
當for回圈或者while回圈中的break執行 else中的代碼將不會執行
"""
- 字串
字串 -> 有序的字符序列- 索引
從左到右0,1,2…
從右到左-1,-2,-3… - 切片 [start,end,step] 范圍[start,end)
- 常見操作
- len(str) 獲取字串長度
- mystr = “”“文本內容”"" 保留拷貝的文本格式
- mystr.find(“str”) 獲取對應字串的下標索引,如果未查詢到,回傳-1;
- mystr.index(“str”) 獲取對應字串的下標索引,如果未查詢到,回傳例外;
- mystr.count(str,start=0,end=len(myStr)) 回傳str在start和end之間在mystr中出現的次數;
- mystr.replace(str1,str2,n) 把myStr中的str1替換成str2;如果n指定,則不超過n次;
- mystr.split(str=" ",2) 以str為分隔符,切片mystr,回傳一個串列;如果n指定,則僅分隔n個字串;
- mystr.capitalize() 把字串的第一個字符大寫;
- mystr.title() 把字串的每個單詞首字母大寫;
- mystr.startswith(obj)檢查字串是否是以 obj開頭, 是則回傳 True,否則回傳 False;
- mystr.endswith(obj) 檢查字串是否以obj結束,如果是回傳True,否則回傳 False;
- mystr.lower() 轉換字串中所有大寫字符為小寫;
- mystr.upper() 轉換字串中的小寫字母為大寫;
- mystr.ljust(width,fillchar) 回傳一個原字串左對齊,并使用指定fillchar[默認空格]填充至長度 width 的新字串
- mystr.rjust(width,fillchar) 回傳一個原字串右對齊,并使用指定fillchar[默認空格]填充至長度 width 的新字串
- mystr.center(width,fillchar) 回傳一個原字串居中,并使用指定fillchar[默認空格]填充至長度 width 的新字串
- mystr.lstrip() 洗掉 mystr 左邊的空白字符
- mystr.rstrip() 洗掉 mystr 字串末尾的空白字符
- mystr.strip() 洗掉mystr字串兩端的空白字符
- mystr.rfind(str, start=0,end=len(mystr) ) 類似于find(),不過是從右邊開始.
- mystr.rindex( str, start=0,end=len(mystr)) 類似于 index(),不過是從右邊開始
- mystr.partition(str) 把mystr以str分割成三部分,str前,str和str后
- mystr.rpartition(str) 類似于 partition()函式,不過是從右邊開始.
- mystr.splitlines() 按照行分隔,回傳一個包含各行作為元素的串列
- mystr.isalpha() 如果 mystr 所有字符都是字母 則回傳 True,否則回傳 False
- mystr.isdigit() 如果 mystr 只包含數字則回傳 True 否則回傳 False.
- mystr.isalnum() 如果 mystr 所有字符都是字母或數字則回傳 True,否則回傳 False
- mystr.isspace() 如果 mystr 中只包含空格,則回傳 True,否則回傳 False.
- mystr.join(str) mystr中每個元素后面插入str,構造出一個新的字串
- 索引
串列
- 定義
my_list =[元素1,元素2,…] - 索引
- 從左到右0,1,2…
- 從右到左-1,-2,-3…
- 串列的回圈遍歷
- for回圈
- while回圈
namesList = ['xiaoWang','xiaoZhang','xiaoHua']
for name in namesList:
print(name)
length = len(namesList)
i = 0
while i<length:
print(namesList[i])
i+=1
- 常見操作
- 添加元素
- append
添加一個整體 - extend
添加一個可以遍歷的物件;將另一個集合中的元素逐一添加到串列中 - insert(index, object)
在指定位置index前插入元素object
- append
>>> a = [1, 2] >>> b = [3, 4] >>> a.append(b) >>> a [1, 2, [3, 4]] >>> a.extend(b) >>> a [1, 2, [3, 4], 3, 4] >>> a.insert(1, 3) >>> a [1, 3, 2, [3, 4], 3, 4]- 修改元素
A = ['xiaoWang','xiaoZhang','xiaoHua'] #修改元素 A[1] = 'xiaoLu'- 查找元素
- in, not in
nameList = ['xiaoWang','xiaoZhang','xiaoHua'] findName = input('請輸入要查找的姓名:') #查找是否存在 if findName in nameList: print('找到了') else: print('沒有找到')- index
回傳查找元素的下標索引 - count
>>> a = ['a', 'b', 'c', 'a', 'b'] >>> a.index('a', 1, 3) # 注意是左閉右開區間 Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: 'a' is not in list >>> a.index('a', 1, 4) 3 >>> a.count('b') 2 >>> a.count('d') 0 - 洗掉元素
- del
根據下標進行洗掉
可以用來洗掉物件,提前釋放記憶體 - pop
洗掉最后一個元素,且會有一個回傳值 - remove
根據元素的值進行洗掉
movieName = ['加勒比海盜','駭客帝國','第一滴血','指環王','霍位元人','速度與激情'] del movieName[2] #根據下標進行洗掉 movieName.pop() #洗掉最后一個元素 movieName.remove('指環王') #根據元素的值進行洗掉 - del
- 排序
sort,reverse
>>> a = [1, 4, 2, 3] >>> a [1, 4, 2, 3] >>> a.reverse() #降序 >>> a [3, 2, 4, 1] >>> a.sort() >>> a [1, 2, 3, 4] >>> a.sort(reverse=True) >>> a [4, 3, 2, 1] - 添加元素
- 串列的嵌套
schoolNames = [['北京大學','清華大學'],['南開大學','天津大學','天津師范大學'],['山東大學',["新東方", "藍翔"],'中國海洋大學']]
name = schoolNames[1][1]
print(name)
元組
串列是可變的,元組是不可變的
- 定義
my_tuple = (元素1,元素2,…) - 注意
如果元組只有一個元素,不為元組型別;可以加個逗號
(1)–> int;(1,)–>tuple - 常見操作
- 訪問元組
通過下標索引 - 查找元素
- index
- count
- 訪問元組
字典
鍵值對{key:value,…};字典是無序的,可變的
-
定義
my_dict = {key1:value1,key2:value2,…}
key值型別必須是不可變的(如串列、字典等都不可),且不能重復(才能完成1對1),一般都使用字串 -
常見操作
-
修改元素/添加元素
格式:字典名[key] = value
如果key不存在,則添加一組鍵值對;如果key存在,則會覆寫此key原來的值 -
洗掉元素
- del
洗掉指定元素,也可以洗掉整個字典 - clear
清空整個字典
>>> info = {'name':'班長', 'sex':'f', 'address':'地球亞洲中國北京'} >>> del info['name'] >>> print('洗掉后,%s' % info['name']) Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'name' del info #洗掉整個字典 info.clear() #清空整個字典 結果為{} - del
-
len() 回傳鍵值對的個數
-
keys 回傳一個包含字典所有key的串列
-
values 回傳一個包含字典所有value的串列
-
items 回傳一個包含所有(鍵,值)元祖的串列
-
-
遍歷
my_dict = {"name": "小紅", "age": 22, "no": "009"}
# 遍歷-key
for key in my_dict.keys():
print(key)
# 遍歷value
for value in my_dict.values():
print(value)
# 遍歷items
for item in my_dict.items():
print(item[0])
# 通過設定兩個臨時變數
for key, value in my_dict.items():
print("key:", key)
print("value:", value)
# enumerate(串列名) 函式
# enumerate() 函式用于將一個可遍歷的資料物件(如串列、元組或字串)組合為一個索引序列,同時列出資料和資料下標
my_list = list("abcd")
# 不僅要獲取串列中的元素 而且需要知道這個元素下標索引
for i, value in enumerate(my_list):
print(i,value)
拆包
變數名和值一一對應
可以把函式回傳值直接拆包
name,age,no,address = ("zhangsan",20,1,"didian")
name,age,no,address = ["zhangsan",20,1,"didian"]
name,age,no,address = {"name":"zhangsan","age":20,"no":1,"address":"didian"} #取到的是key值
#批量定義變數
num1, num2, num3, num4 = 10, 20, 30, 40
函式
- 定義
def 函式名(形參1,形參2,...):
函式體
# pass占位,防止錯誤
- 呼叫
函式名(實參1,實參2,...)
- 預設引數
給形參設定一個默認值;呼叫函式時,可根據實際需要決定是否傳遞引數必須先定義后呼叫,有先后順序
注意:在定義函式時若某個形參使用了預設引數,那么其后面的形參都需要用預設引數 - 四種函式型別
- 無引數、無回傳值
- 無引數、有回傳值
- 有引數、無回傳值
- 有引數、有回傳值
- 函式可嵌套呼叫
- 呼叫函式方式
- 位置引數
使用位置引數呼叫函式,需要注意實參的位置–>實參的位置需要和形參的位置一一對應 - 關鍵字引數
呼叫函式的時候使用的是函式的形參名,位置不需要完全對應
- 位置引數
- 函式回傳值return
只要函式中執行了return,提前結束函式的執行,且其后的代碼將不再執行;可以通過return使執行的函式提前結束以優化性能
可以直接回傳不同型別的資料;如return a,b --> tuple return […] --> list ; return{ “key”:value,“key2”:value,…} --> dict ; - 函式的檔案說明
- 如果一個自定義函式沒有檔案說明 ,默認用help會列印函式上面的注釋
- 可以在def下方用""" “”"自動生成檔案說明
- 變數
- 區域變數
定義在函式內部,作用域僅在函式內部 - 全域變數
定義在函式外部,作用域為整個模塊;
標識全域變數 --> global 變數名 - 優先級
區域變數>全域變數;python會現在函式內部找變數,若無,再在外部找
- 區域變數
- 匿名函式lambda
# 對函式的簡寫
f = lambda a, b : a + b
print(f(10, 20))
# 等價于
# def add2num(a, b):
# return a + b
# 函式作為引數傳遞
# f = lambda x,y:x+y
def fun(a, b, opt):
result = opt(a, b)
print("result = %d" % result)
fun(1, 2, lambda x,y:x+y)
# 自定義排序(最外層肯定是串列)
# 格式: 串列名.sort(key=lambda 串列的元素(臨時變數): 臨時變數[key])
stus = [{"name": "zhangsan", "age": 18}, {"name": "lisi", "age": 19}, {"name": "wangwu", "age": 17}]
# 按照年齡排序
stus.sort(key=lambda my_dict:my_dict["age"])
# 按照名字排序
stus.sort(key=lambda my_dict:my_dict["name"])
# 串列中的串列嵌套
my_list = [[10, 8, 9], [7, 10, 19], [9, 10, 29]]
# 按照串列元素(小串列)最后一個元素排序
my_list.sort(key=lambda new_list:new_list[2], reverse=True)
- 串列推導式
快速創建有規律的串列
# 使用串列推導式 快速創建一個串列
my_list = [ i for i in range(1, 31)]
# 等價于
# my_list = []
# for i in range(1, 101):
# my_list.append(i)
# 得到一個有30個哈哈的串列
my_list = ["哈哈" for i in range(30)]
# 定義一個串列 保存資料[1, 50]之間的偶數
# 串列推導式
my_list = [ i for i in range(1, 51) if i % 2 == 0]
# 等價于
# my_list = []
# for i in range(1, 51):
# # 判斷是否是偶數
# if i % 2 == 0:
# my_list.append(i)
#
# print(my_list)
檔案操作
- 檔案打開與關閉
# 打開一個檔案 以只讀方式 回傳一個檔案物件
# 如果使用r模式打開檔案,如果檔案存在,直接打開;如果檔案不存在 會報錯
f = open("hm.txt", "r")
# 關閉檔案(打開一個檔案就需要消耗記憶體)
f.close()
# 打開一個檔案 以只寫方式 回傳一個檔案物件;如果以w方式打開檔案 會把原來檔案的資料清空 然后在寫入
# 如果使用w模式打開檔案 如果檔案存在 直接打開;如果檔案不存在 會創建一個檔案 然后打開
open("hm.txt", "w")
f.close()
# a 追加資料
# f = open(file_name, "a")
# f.write("nihao")
# f.close()
- 檔案讀寫
file_name = "hm.txt"
# <1>寫資料(write)
# f = open(file_name, "w")
# f.write("hello world")
# f.close()
# <2>讀資料(read) 如果使用字串方便
# f = open(file_name, "r")
# ret = f.read()
# print(ret)
# f.close
# <3>讀資料(readlines) 如果使用串列方便
# f = open(file_name, "r")
# 把每行的資料保存到串列中
# ret = f.readlines()
# print(ret)
# f.close()
# 中文讀寫
# f = open("hmhm.txt", "w", encoding="utf-8")
# # 寫入資料
# # 默認情況下如果在windows電腦中(中國) 保存中文編碼格式為gbk (mac電腦或者是linux 沒有問題)
# # 如果其他字符 例如abcd 編碼格式為utf-8
# f.write("你好世界")
# # 關閉檔案
# f.close()
- 其他操作
匯入os模塊
import os
# 檔案/檔案夾重命名
os.rename(old_fileName,new_fileName)
# 洗掉檔案
os.remove(fileName)
# 創建檔案夾
os.mkdir(dirName)
# 獲取當前目錄(絕對路徑)
result = os.getwd()
# 改變默認目錄
os.chdir("../")
# 獲取目錄串列
my_list = os.listdir()
# 洗掉檔案夾
os.rmdir(dirName)
- 其他型別檔案操作
- txt檔案
# 讀取 # 通過此方式打開檔案 不需要關閉 # as 是給檔案起了名字 with open("hm.txt", "r", encoding="utf-8") as f: result = f.read() # 寫入 f = open("hm.txt", "w", encoding="utf-8") f.write("hello python!!!") f.close()- excel檔案
# 讀取 import xlrd data = xlrd.open_workbook("student.xlsx") # 獲取串列 table = data.sheet_by_index(0) # 獲取所有的行數 nrows = table.nrows # 獲取所有的列數 ncols = table.ncols # 獲取第一行的資料 first_row_name_list = table.row_values(0) print(first_row_name_list) # 定義一個串列保存所有行的資料 info_list = [] # 遍歷所有行 for rownum in range(1, nrows): row = table.row_values(rownum) if row: info_list.append(row) print(info_list) # 寫入 import xlsxwriter # 打開student.xlsx檔案 workbook = xlsxwriter.Workbook("student.xlsx") # 創建一張作業表 worksheet = workbook.add_worksheet() # 設定第一行資訊 worksheet.write(0, 0, "學號") worksheet.write(0, 1, "姓名") worksheet.write(0, 2, "年齡") # 學生資訊串列 student_list = [{"name": "小明", "age": 20, "no": "20170901001"}, {"name": "小紅", "age": 21, "no": "20170901002"}, {"name": "小剛", "age": 20, "no": "20170901003"}, {"name": "小海", "age": 23, "no": "20170901004"}, {"name": "小陽", "age": 25, "no": "20170901005"}] # 遍歷串列 for i, info in enumerate(student_list): # 寫入資料 # write(第x行, 第x列, 寫入的資料) worksheet.write(i + 1, 0, info["no"]) worksheet.write(i + 1, 1, info["name"]) worksheet.write(i + 1, 2, info["age"]) # 關閉檔案 workbook.close()- json檔案
# 讀取 import json # 將json物件轉成字典 -> 進行解碼 with open("hm.json", "r", encoding="utf-8") as f: # 獲取檔案中資料 -> 字典 new_dict = json.load(f) # 查看型別 print(type(new_dict)) # 獲取名字 print(new_dict["name"]) # 獲取年齡 print(new_dict["age"]) # 獲取學號 print(new_dict["no"]) # 寫入 import json # 定義一個字典 my_dict = {"name": "老王", "age": 30, "no": "007"} # 將字典轉成json -> 進行編碼 json_str = json.dumps(my_dict) # 列印json字串 print(type(json_str)) # 把json資料寫入到檔案中 with open("hm.json", "w", encoding="utf-8") as f: f.write(json_str)- xml檔案
// xml示例檔案 <list> <music title="再見理想"> <format>盒帶</format> <year>1986</year> <month>3</month> <stars>10</stars> <description>Beyond出品</description></music><music title="光輝歲月"> <format>盒帶</format> <year>1987</year> <month>1</month> <stars>9</stars> <description>Beyond出品</description></music> <music title="長城"> <format>盒帶</format> <year>1992</year> <month>8</month> <stars>10</stars> <description>Beyond出品</description></music><music title="海闊天空"> <format>盒帶</format> <year>1993</year> <month>6</month> <stars>10</stars> <description>Beyond出品</description></music></list># 讀取 import xml.dom.minidom # 定義一個變數保存檔案名 file_name = "xml.xml" #打開xml檔案 domTree = xml.dom.minidom.parse(file_name) # 回傳檔案的根節點 root = domTree.documentElement # 回傳帶有指定標簽名的物件的集合(在集合中獲取所有電影) musics = root.getElementsByTagName("music") # 列印每部電影的詳細資訊 for music in musics: print("------音樂------") # 如果元素的屬性為title if music.hasAttribute("title"): print("歌名: %s" % music.getAttribute("title")) # 格式 type = music.getElementsByTagName("format")[0] print("-格式: %s" % type.childNodes[0].data) year = music.getElementsByTagName("year")[0] print("-年份: %s" % year.childNodes[0].data) month = music.getElementsByTagName("month")[0] print("-月份: %s" % month.childNodes[0].data) start = music.getElementsByTagName("stars")[0] print("-星數: %s" % start.childNodes[0].data) desc = music.getElementsByTagName("description")[0] print("-描述:%s" % desc.childNodes[0].data)
面向物件基礎
-
區分
- 面向程序
根據業務邏輯從上到下寫代碼 - 面向物件(封裝成類,可復用)
將資料與函式系結到一起,進行封裝,這樣能夠更快速的開發程式,減少了重復代碼的重寫程序
面向物件三大特性:封裝、繼承、多型
- 面向程序
-
類和物件
- 定義
- 類(抽象)
類名、屬性、方法 - 實體物件
- 類(抽象)
- 自定義類
class 類名:
方法串列
# class Hero: # 經典類(舊式類) # class Hero(): class Hero(object): # 新式類 def info(self): print("英雄各有見,何必問出處,") # object 是Python 里所有類的最頂級父類; # 類名 的命名規則按照"大駝峰命名法"; # info 是一個實體方法,第一個引數一般是self,表示實體物件本身,當然了可以將self換為其它的名字,其作用是一個變數 這個變數指向了實體物件- 創建物件
物件名1 = 類名()
物件名2 = 類名()
物件名3 = 類名()
class Hero(object): # 新式類 # 1、定義實體方法 def info(self): """當物件呼叫實體方法時,Python會自動將物件本身的參考做為引數, 傳遞到實體方法的第一個引數self里""" print(self) print("self各不同,物件是出處,") # Hero這個類 2、實體化了一個物件 taidamier(泰達米爾) taidamier = Hero() # 3、物件呼叫實體方法info(),執行info()里的代碼 # . 表示選擇屬性或者方法 taidamier.info()- 添加和獲取物件的屬性
class Hero(object): def move(self): """實體方法""" print("正在前往事發地點...") def attack(self): print("發出了一招強力的普通攻擊...") # 實體化了一個英雄物件 泰達米爾 taidamier = Hero() # 給物件添加屬性,以及對應的屬性值 taidamier.name = "泰達米爾" # 姓名 taidamier.hp = 2600 # 生命值 taidamier.atk = 450 # 攻擊力 taidamier.armor = 200 # 護甲值 # 通對.成員選擇運算子,獲取物件的屬性值 print("英雄 %s 的生命值 :%d" % (taidamier.name, taidamier.hp)) print("英雄 %s 的攻擊力 :%d" % (taidamier.name, taidamier.atk)) print("英雄 %s 的護甲值 :%d" % (taidamier.name, taidamier.armor)) # 通過.成員選擇運算子,獲取物件的實體方法 taidamier.move() taidamier.attack()- 在方法內通過self獲取物件屬性
class Hero(object): def move(self): print("正在前往事發地點...") def attack(self): print("發出了一招強力的普通攻擊...") def info(self): """在類的實體方法中,通過self獲取該物件的屬性""" print("英雄 %s 的生命值 :%d" % (self.name, self.hp)) print("英雄 %s 的攻擊力 :%d" % (self.name, self.atk)) print("英雄 %s 的護甲值 :%d" % (self.name, self.armor)) # 實體化了一個英雄物件 泰達米爾 taidamier = Hero() # 給物件添加屬性,以及對應的屬性值 taidamier.name = "泰達米爾" # 姓名 taidamier.hp = 2600 # 生命值 taidamier.atk = 450 # 攻擊力 taidamier.armor = 200 # 護甲值 # 通過.成員選擇運算子,獲取物件的實體方法 taidamier.info() # 只需要呼叫實體方法info(),即可獲取英雄的屬性 taidamier.move() taidamier.attack() - 定義
-
魔法方法
__開頭,__結尾的方法,是python內置的方法,在特殊情況下被python執行(python可以監聽到你使用自定義類創建一個物件)
在自定義類中重寫魔法方法- __init__()方法
監聽python使用其類創建物件完成,給這個物件設定屬性
在創建一個物件時默認被呼叫,不需要手動呼叫
class Hero(object): """定義了一個英雄類""" def __init__(self, name, skill, hp, atk, armor): """ __init__() 方法,用來做變數初始化 或 賦值 操作""" self.name = name self.skill = skill self.hp = hp self.atk = atk self.armor = armor def move(self): """實體方法""" print("%s 正在前往事發地點..." % self.name) def attack(self): print("發出了一招強力的%s..." % self.skill) def info(self): print("英雄 %s 的生命值 :%d" % (self.name, self.hp)) print("英雄 %s 的攻擊力 :%d" % (self.name, self.atk)) print("英雄 %s 的護甲值 :%d" % (self.name, self.armor)) # 實體化英雄物件時,引數會傳遞到物件的__init__()方法里 taidamier = Hero("泰達米爾", "旋風斬", 2600, 450, 200) gailun = Hero("蓋倫", "大寶劍", 4200, 260, 400) # 不同物件的屬性值單獨保存 print(id(taidamier.name)) print(id(gailun.name)) # 同一個類的不同物件,實體方法共享 print(id(taidamier.move())) print(id(gailun.move()))- __new__()方法
監聽python使用其類創建物件,并回傳物件 --> init
class A(object): def __init__(self): print("這是 init 方法") def __new__(cls): print("這是 new 方法") return object.__new__(cls) A() # __new__至少要有一個引數cls,代表要實體化的類,此引數在實體化時由Python解釋器自動提供 # __new__必須要有回傳值,回傳實體化出來的實體,這點在自己實作__new__時要特別注意,可以return父類__new__出來的實體,或者直接是object的__new__出來的實體 # __init__有一個引數self,就是這個__new__回傳的實體,__init__在__new__的基礎上可以完成一些其它初始化的動作,__init__不需要回傳值 # 我們可以將類比作制造商,__new__方法就是前期的原材料購買環節,__init__方法就是在有原材料的基礎上,加工,初始化商品環節- __str__()方法
監聽物件屬性資訊的變化,會回傳一個字串,不能添加引數,一般用于除錯代碼
如果類中實作了__str__()方法,列印物件名,會輸出__str__()方法的回傳值
class Hero(object): def __init__(self, name, skill, hp, atk, armor): self.name = name self.skill = skill self.hp = hp self.atk = atk self.armor = armor def move(self): print("%s 正在前往事發地點..." % self.name) def attack(self): """實體方法""" print("發出了一招強力的%s..." % self.skill) def __str__(self): return "英雄 <%s> 資料: 生命值 %d, 攻擊力 %d, 護甲值 %d" % (self.name, self.hp, self.atk, self.armor) taidamier = Hero("泰達米爾", "旋風斬", 2600, 450, 200) gailun = Hero("蓋倫", "大寶劍", 4200, 260, 400) # 如果沒有__str__ 則默認列印物件在記憶體的地址, # 當類的實體化物件 擁有 __str__ 方法后,那么列印物件則列印 __str__ 的回傳值, print(taidamier) print(gailun)- __del__()方法
監聽物件銷毀后呼叫的方法
class Hero(object): # 初始化方法,創建完物件后會自動被呼叫 def __init__(self, name): print('__init__方法被呼叫') self.name = name # 當物件被洗掉時,會自動被呼叫 def __del__(self): print("__del__方法被呼叫") print("%s 被 GM 干掉了..." % self.name) # 創建物件 taidamier = Hero("泰達米爾") # 洗掉物件 print("%d 被洗掉1次" % id(taidamier)) del(taidamier) gailun = Hero("蓋倫") gailun1 = gailun gailun2 = gailun print("%d 被洗掉1次" % id(gailun)) del(gailun) print("%d 被洗掉1次" % id(gailun1)) del(gailun1) print("%d 被洗掉1次" % id(gailun2)) del(gailun2)- 記憶體回識訓制(粗略)
當使用del() 洗掉變數指向的物件時,則會減少物件的參考計數,如果物件的參考計數不為1,那么會讓這個物件的參考計數減1,當物件的參考計數為0的時候,則物件才會被真正洗掉(記憶體被回收)
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-3ZR9vzfA-1612875771802)(en-resource://database/1124:1)] @w=300h=400 - 注意
在類內部獲取 屬性 和 實體方法,通過self獲取;
在類外部獲取 屬性 和 實體方法,通過物件名獲取,
- __init__()方法
-
繼承
- 單繼承
只繼承一個父類
# 定義一個Master類 class Master(object): def __init__(self): # 屬性 self.kongfu = "古法煎餅果子配方" # 實體方法 def make_cake(self): print("按照 <%s> 制作了一份煎餅果子..." % self.kongfu) # 定義Prentice類,繼承Master class Prentice(Master): # 子類可以繼承父類所有的屬性和方法 pass # laoli = Master() # print(laoli.kongfu) # laoli.make_cake() damao = Prentice() # 創建子類實體物件 print(damao.kongfu) # 子類物件可以直接使用父類的屬性 damao.make_cake() # 子類物件可以直接使用父類的方法- 多繼承
如果多個父類中有同名的 屬性和方法,則默認使用第一個父類的屬性和方法(根據類的魔法屬性mro的順序來查找)
class Master(object): def __init__(self): self.kongfu = "古法煎餅果子配方" def make_cake(self): print("[古法] 按照 <%s> 制作了一份煎餅果子..." % self.kongfu) def dayandai(self): print("師傅的大煙袋..") class School(object): def __init__(self): self.kongfu = "現代煎餅果子配方" def make_cake(self): print("[現代] 按照 <%s> 制作了一份煎餅果子..." % self.kongfu) def xiaoyandai(self): print("學校的小煙袋..") class Prentice(Master, School): # 多繼承(Master在前) pass damao = Prentice() print(damao.kongfu) # 執行Master的屬性 damao.make_cake() # 執行Master的實體方法 # 子類的魔法屬性__mro__決定了屬性和方法的查找順序 print(Prentice.__mro__) damao.dayandai() # 不重名不受影響 damao.xiaoyandai()- 重寫
子類繼承父類,做自己特有的事情
子類和父類的方法名和屬性名相同,則默認使用子類的 - 子類呼叫父類同名屬性和方法(已重寫)
父類類名.父類方法(self) --> self指定呼叫的物件
class Master(object): def make_cake(self): print("按照 [古法] 制作了一份煎餅果子...") class School(object): def make_cake(self): print(" 按照 [現代] 制作了一份煎餅果子...") # 多繼承,繼承了多個父類 class Prentice(School, Master): # 實體方法 def make_cake(self): print("按照 [貓氏] 制作了一份煎餅果子...") # 呼叫父類方法格式:父類類名.父類方法(self) def make_old_cake(self): # 呼叫父類Master的實體方法 Master.make_cake(self) def make_new_cake(self): # 呼叫父類School的實體方法 School.make_cake(self) # 實體化物件,自動執行子類的__init__方法 damao = Prentice() damao.make_cake() # 呼叫子類的方法(默認重寫了父類的同名方法) damao.make_old_cake() # 進入實體方法去呼叫父類Master的方法 damao.make_new_cake() # 進入實體方法去呼叫父類School的方法 damao.make_cake() # 呼叫本類的實體方法- super()方法
super()默認會呼叫第一個父類的方法(適用于單繼承或者只想使用第一個父類方法的多繼承)
class Master(object): def make_cake(self): print("按照 [古法] 制作了一份煎餅果子...") class School(Master): def make_cake(self): print("按照 [現代] 制作了一份煎餅果子...") # 執行父類的實體方法 -->可以直接在子類一個方法里面呼叫父類 super().make_cake() class Prentice(School, Master): def make_cake(self): print("按照 [貓氏] 制作了一份煎餅果子...") def make_all_cake(self): # 方式1. 指定執行父類的方法(代碼臃腫) # School.make_cake(self) # Master.make_cake(self) # 方法2. super() 帶引數版本,只支持新式類 # super(Prentice, self).make_cake() # self.make_cake() # 方法3. super()的簡化版,只支持新式類 # 執行父類的 實體方法 super().make_cake() damao = Prentice() damao.make_cake() damao.make_all_cake() - 單繼承
-
私有屬性和私有方法
在屬性和方法名前面加了2個下劃線’__’,則表明該屬性和方法是私有權限,否則為公有權限 -->類似java里的public&private
1. 類的私有屬性 和 私有方法,都不能通過物件直接訪問,但是可以在本類內部訪問;
2. 類的私有屬性 和 私有方法,都不會被子類繼承,子類也無法訪問;
3. 私有屬性 和 私有方法 往往用來處理類的內部事情,不通過物件處理,起到安全作用,class Master(object): def __init__(self): self.kongfu = "古法煎餅果子配方" def make_cake(self): print("[古法] 按照 <%s> 制作了一份煎餅果子..." % self.kongfu) class School(object): def __init__(self): self.kongfu = "現代煎餅果子配方" def make_cake(self): print("[現代] 按照 <%s> 制作了一份煎餅果子..." % self.kongfu) class Prentice(School, Master): def __init__(self): self.kongfu = "貓氏煎餅果子配方" # 私有屬性,可以在類內部通過self呼叫,但不能通過物件訪問 self.__money = 10000 # 私有方法,可以在類內部通過self呼叫,但不能通過物件訪問 def __print_info(self): print(self.kongfu) print(self.__money) def make_cake(self): self.__init__() print("[貓氏] 按照 <%s> 制作了一份煎餅果子..." % self.kongfu) def make_old_cake(self): Master.__init__(self) Master.make_cake(self) def make_new_cake(self): School.__init__(self) School.make_cake(self) class PrenticePrentice(Prentice): pass damao = Prentice() # 物件不能訪問私有權限的屬性和方法# print(damao.__money) # damao.__print_info() pp = PrenticePrentice() # 子類不能繼承父類私有權限的屬性和方法 print(pp.__money) pp.__print_info()- 修改私有屬性的值
間接通過公有方法
class Master(object): def __init__(self): self.kongfu = "古法煎餅果子配方" def make_cake(self): print("[古法] 按照 <%s> 制作了一份煎餅果子..." % self.kongfu) class School(object): def __init__(self): self.kongfu = "現代煎餅果子配方" def make_cake(self): print("[現代] 按照 <%s> 制作了一份煎餅果子..." % self.kongfu) class Prentice(School, Master): def __init__(self): self.kongfu = "貓氏煎餅果子配方" # 私有屬性,可以在類內部通過self呼叫,但不能通過物件訪問 self.__money = 10000 # 現代軟體開發中,通常會定義get_xxx()方法和set_xxx()方法來獲取和修改私有屬性值, # 回傳私有屬性的值 def get_money(self): return self.__money # 接收引數,修改私有屬性的值 def set_money(self, num): self.__money = num def make_cake(self): self.__init__() print("[貓氏] 按照 <%s> 制作了一份煎餅果子..." % self.kongfu) def make_old_cake(self): Master.__init__(self) Master.make_cake(self) def make_new_cake(self): School.__init__(self) School.make_cake(self) class PrenticePrentice(Prentice): pass damao = Prentice() # 物件不能訪問私有權限的屬性和方法 # print(damao.__money) # damao.__print_info() # 可以通過訪問公有方法set_money()來修改私有屬性的值 damao.set_money(100) # 可以通過訪問公有方法get_money()來獲取私有屬性的值 print(damao.get_money()) - 修改私有屬性的值
-
多型
定義時的型別和運行時的型別不一樣;python中榷訓型別(重點在于物件引數是否有指定的屬性和方法,如果有就認定合適,而不關心物件的型別是否正確 --> “鴨子型別”)
class F1(object):
def show(self):
print('F1.show')
class S1(F1):
def show(self):
print('S1.show')
class S2(F1):
def show(self):
print('S2.show')
def Func(obj):
# python是弱型別,即無論傳遞過來的是什么,obj變數都能夠指向它,這也就沒有所謂的多型了(榷訓了這個概念)
print(obj.show())
s1_obj = S1()
Func(s1_obj)
s2_obj = S2()
Func(s2_obj)
- 記憶體問題
- 物件需要占用記憶體,且和物件屬性地址不同
- 物件的屬性也要占用記憶體,且和物件的地址不同
- 不同的物件,呼叫物件方法的地址相同(因為方法中有形參self,可以區分是哪個物件呼叫的)
- python的小整數快取池(-5~256之間) id相同
- 字串 元組 字典 串列 也有快取池(小于2kb)
- 類屬性和實體屬性
# 類屬性就是類物件所擁有的屬性
class People(object):
name = 'Tom' # 公有的類屬性
__age = 12 # 私有的類屬性
p = People()
# 實體屬性就是物件屬性
class People(object):
address = '山東' # 類屬性
def __init__(self):
self.name = 'xiaowang' # 實體屬性
self.age = 20 # 實體屬性
p = People()
# 若需要在類外修改類屬性,必須通過類物件(Peole.name = 'xx')去參考然后進行修改,
# 如果通過實體物件去參考,會產生一個同名的實體屬性,這種方式修改的是實體屬性,不會影響到類屬性,并且之后如果通過實體物件去參考該名稱的屬性,實體屬性會強制屏蔽掉類屬性,即參考的是實體屬性,除非洗掉了該實體屬性
- 類中的方法
- 實體方法
- 類方法
class People(object): country = 'china' #類方法,用classmethod來進行修飾 @classmethod def get_country(cls): return cls.country @classmethod def set_country(cls,country): cls.country = country p = People() print(p.get_country()) #可以用過實體物件參考 print(People.get_country()) #可以通過類物件參考 # 對類屬性進行修改 p.set_country('japan') print(p.get_country()) print(People.get_country())- 靜態方法
class People(object): country = 'china' #靜態方法 @staticmethod def get_country(): #沒有默認形參 return People.country p = People() # 通過物件訪問靜態方法 p.get_contry() # 通過類訪問靜態方法 print(People.get_country())- 總結
- 實體方法(物件方法) -> 場景很多 - 定義格式: def 實體方法名(self): - 呼叫格式: 物件名.實體方法名() - 使用場景: 在方法中需要self - 類方法-> 對私有類屬性取值或者賦值 - 定義格式: @classmethod def 類方法名(cls): - 呼叫格式: 類名.類方法名() 或者 物件名.類方法名() - 使用場景: 在方法中需要cls(類名) - 靜態方法 -> 一般不用 - 定義格式: @staticmethod def 靜態方法名(): - 呼叫格式: 類名.類方法名() 或者 物件名.類方法名() - 使用場景: 在方法中不需要self 也不需要cls - 單例模式(設計模式)–> 節約記憶體
- 定義
確保某一個類只有一個實體,而且自行實體化并向整個系統提供這個實體,這個類稱為單例類,單例模式是一種物件創建型模式
單例模式:在程式中這個類創建出來的物件只有一個,也就是只占用一份記憶體;也**只會運行一次__init __()方法 **–>保證物件地址唯一,保證其物件的屬性只會被賦值一次
- 定義
# 實體化一個單例
class Singleton(object):
__instance = None
__is_first = True
def __new__(cls, age, name):
if not cls.__instance:
cls.__instance = object.__new__(cls)
return cls.__instance
def __init__(self, age, name):
if self. __is_first:
self.age = age
self.name = name
Singleton. __is_first = False
a = Singleton(18, "小明")
b = Singleton(28, "小明")
print(id(a))
print(id(b))
print(a.age)
print(b.age)
a.age = 19
print(b.age)
例外
- 捕獲例外
- try…except
try: 執行可能發生例外的代碼 except (例外型別1,例外型別2,...): #單個例外,多個例外,所有例外(except Exception:...) 如果發生例外執行的代碼- 獲取例外資訊描述
try: 執行可能發生例外的代碼 except (例外型別1,例外型別2,...)as 臨時變數: 可以獲得臨時變數 #print("exceptions",e)- try…exceprt…else
else后跟未發生例外的代碼 - try…except…finally
finally后跟必須要執行的代碼
- 例外的傳遞
- try嵌套中
try嵌套,那么如果里面的try沒有捕獲到這個例外,那么外面的try會接收到這個例外,然后進行處理,如果外邊的try依然沒有捕獲到,那么再進行傳遞
import time try: f = open('test.txt') try: while True: content = f.readline() if len(content) == 0: break time.sleep(2) print(content) finally: f.close() print('關閉檔案') except: print("沒有這個檔案")- 函式嵌套中
def my_func1(): try: print(num) except: print("例外") def my_func2(): my_func1() def my_func3(): my_func2() my_func3() - try嵌套中
模塊
- 模塊介紹
變數(全域變數 區域變數 實體屬性 類屬性)–> 方法(實體方法 類方法 靜態方法)–>模塊–> 包–>工程(專案)- import
引入格式:import 模塊名
使用格式:模塊名.全域變數名;模塊名.函式名;模塊名.類名 - from…import
格式:from 模塊名 import 全域變數 函式 類
注意:和本模塊名字沖突
from 模塊名 *:全部匯入,使用時不需要寫模塊名 - 關鍵詞as–>別名
- 關鍵詞__all__
如果一個模塊中使用了__all__,串列中的字串才可以在其他模塊中使用;但其他模塊必須是通過from…import * 方式匯入的模塊 - 包
匯入格式:包名.模塊名 as 別名
- import
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/258429.html
標籤:python
