計算機的硬件由:CPU /內存 /主板 /硬盤 /顯卡等組成java
內存:python
優勢:存取速度快mysql
缺點:斷電後數據所有丟失linux
硬盤:c++
優勢:斷電後數據也會永久保存git
缺點:存取速度遠遠慢於內存程序員
操做系統用於協同或控制硬件之間進行工做面試
編程語言的開發者寫的一個工具,將用戶寫的代碼轉換成二進制交給操做系統去執行redis
對於計算機而言,不管文件儲存 / 網絡傳輸等本質上都是二進制.微信/QQ等發的信息,圖片,視頻都是二進制算法
進制:
2進制: 計算機內部
8進制
10進制:人使用計算機通常都是10進制,計算機內部會將其轉換成二進制
16進制:通常用於表示(用更短的內容表示更多的東西.通常是: \x 開頭
ASCII :8位表示一個東西,只能識別英文
Unicode(萬國碼): 一箇中文或字母等於四個字節,最多32位表示,內存進行數據計算時使用
utf-8:給萬國碼壓縮,一箇中文等於3個字節,一個英文一個字節,通常網絡傳輸和文件存儲時使用此編碼
gbk : 一箇中文兩個字節
gb2312
注意:文件以什麼方式保存就要以什麼方式打開
py2默認解釋器編碼:ASCII
py3默認解釋器編碼:utf-8
如想修改默認編碼,則可使用:
# -*- coding:utf-8 -*-
爲何要有變量?
爲某個值建立一個「外號」,之後在使用時候經過此外號就能夠直接調用。
輸出:
py2: print '你好' py3: print('你好')
輸入 : 獲得的內容永遠是字符串
py2 raw_input("xxx") py3 input('xxx')
#示例 user_name = input("請輸入你的姓名:") password = input("請輸入你的密碼:") content = "你的用戶名是:" + user_name + "; 你的密碼是:" + password print(content)
# 單行註釋 ''' 多行註釋 '''
# :示例:讓用戶輸入一個數字,猜:若是數字 > 50,則輸出:大了; 若是數字 <= 50 ,則輸出:小了。 num = input('請輸入一個數字') number = int(num) if number > 50: print('大了') else: print('小了')
while 循環
while 條件表達式: 循環體 # 當條件表達式的返回值爲真時,則執行循環體中的語句,執行完畢後,從新判斷條件表達式的返回值,直到表達式的返回的結果爲假時,退出循環.
for 循環
for 某個變量 in 要循環的對象: 循環體 # 其中某個變量是用於保存讀取出的值,對象爲要遍歷或迭代的對象,能夠是任何有序的序列對象,如字符串.列表.元組等.循環體爲一組被重複執行的語句
死循環考慮while, 有限循環優先考慮for循環
break 語句
意思爲結束當前循環
continue 語句
意思:當循環遇到continue時,再也不繼續往下走,而是回到當前循環
%s: (字符串佔位符)
name = input('姓名:') do = input('在幹什麼:') template = "%s在教室,%s。" %(name,do,) print(template)
%d (數字佔位符)
template = "我是%s,年齡%d, 職業%s。" %("alex",73,'講雞湯',) print(template)
%%
name = 'alex' template = "%s如今手機的電量是100%%" %(name,) print(template)
算數運算
示例: 1 ~ 100 之間全部的數相加。 total = 0 count = 1 while count <=100: total += count count += 1 print(total)
賦值運算
邏輯運算
or
對於 or,若是有遇到 value= 1 or 9 第一個值若是是轉換成布爾值若是是真,則value=第一值。 第一個值若是是轉換成布爾值若是是假,則value=第二值。 若是有多個or條件,則從左到右依次進行上述流程
and
對於and,若是遇到 value= 1 and 9 若是第一個值轉換成布爾值是True,則value=第二個值 若是第一個值轉換成布爾值是False,則value=第一個值。 若是有多個and條件,則從左到右依次進行上述流程
優先級
在沒有()的狀況下not 優先級高於 and,and優先級高於or,即爲( )>數學運算>not>and>or,同一優先級從左往右計算
示例: not 2 > 1 and 3 < 4 or 4 > 5 and 2 > 1 and 9 > 8 or 7 < 6 False 3 > 1 and 2 or 2 < 3 and 3 and 4 or 3 > 2 2
表示空(無任何功能,專門用於提供空值)
py2:整型除法只能保留整數位。
from __future__ import division v = 9 /2 print(v) #保留所有值
py3
只有兩個結果:True/False: 0/''/[]/()/{}/set() 轉布爾時爲False,其他結果都爲Ture
upper:轉大寫 lower:轉小寫
name = 'alex' new_name = name.upper() print(new_name) # ALEX
isdigit:判斷是不是數字,但經常使用 isdecimal 來判斷
v = '1' # v = '二' # v = '②' v1 = v.isdigit() # '1'-> True; '二'-> False; '②' --> True v2 = v.isdecimal() # '1'-> True; '二'-> False; '②' --> False v3 = v.isnumeric() # '1'-> True; '二'-> True; '②' --> True print(v1,v2,v3) # 之後推薦用 isdecimal 判斷是不是 10進制的數。
strip: 去除空白,也能夠去除換行符(\n)和指定字符串
v1 = "alex " print(v1.strip()) v1 = "alexa" print(v1.strip('al'))
replace:替換
content = '去你大爺的' con = content.replace('大爺','**') #當替換的內容有多個時,後面能夠加入數字,表明替換前幾個內容 print(con) # 去你**的
split:切割 ,獲得的是一個列表
content = '12|22,33|44' con = content.split('|') print(con) #['12', '22,33', '44']
format:字符串格式化
name = '我是{0},今年{1}'.format('Alex',20,) print(name)
startswith:判斷以什麼開頭 endswith:判斷以什麼結尾 結果爲Ture/False
name = 'alex' flag = name.startswith('al') print(flag) # Ture
encode:轉換編碼
name = '張三' # 解釋器讀取到內存後,按照unicode編碼存儲:8個字節。 v1 = name.encode('utf-8') print(v1) # 轉換成了6個字節
join: 循環某個元素,並以某個東西鏈接起來
name = 'Alex' new_name = '-'.join(name) #注意:join鏈接的必須的字符串,若是不是須要先轉化爲字符串再進行鏈接 print(new-name) # A-l-e-x
isalnum() 判斷字符串是否由字母或數字組成
isalpha() 判斷字符串只有字母組成
append:在列表末追加元素
v = [1,2,3,4,5] v.append(6) print(v) #[1,2,3,4,5,6]
insert:在列表指定索引值前面加入元素
v= [1,2,3,4] v.insert(0,6) print(v) #[6,1,2,3,4]
extend: 逐個加入
v = [1,2,3] name = 'Alex' v.extend(name) #加入的能夠是字符串/元組/列表/集合 print(v) #[1,2,3,A,l,e,x]
remove:刪除指定元素
v = [123,23,45] v.remove(23) print(v) #[123,45]
pop: 根據索引位置進行刪除
v = [123,23,45] a = v.pop(0) #pop()默認刪除最後一個元素,會將刪除的那個元素返回回去 print(v,a) # 123 [23,45]
del ;刪除
v = [123,23,45] del v[0] print(v) #[23,45]
修改
v = [123,23,45] v[0] = 11 print(v) #[11,23,45]
reverse :反轉
v = [123,23,45] v.reverse() print(v) #[45,23,123]
sort: 排序
v= [2,6,4,8,1] v.sort(reverse=True) #從大到小排列 v.sort(reverse=False) #從小到大排列 v.sort() #默認是從小到大排列 print(v)
枚舉和索引
lis = [11,22,33,44] for index ,item in enumerate(lis,1) print(index,item) print(lis.index(33)) # 2
格式
data = {鍵:值,鍵:值,鍵:值,鍵:值,鍵:值,鍵:值,} #鍵值對 嵌套中: # 值能夠用任何東西表示 # 鍵不能用列表/字典/集合(等可變類型)表示,其餘均可以
keys 取全部的鍵
data = {11:22,33:44,55:66} for k in data.keys(): print(k) #11,33,55
values 取全部的值
data = {11:22,33:44,55:66} for v in data.values(): print(v) # 22,44,66
items 取全部的鍵值對
data = {11:22,33:44,55:66} for k,v in data.items(): print(k,v) 注意: a,b,c = [1,2,3] print(a,b,c) #a=1,b=2,c=3
get取值
info = {'k1':'v1','k2':'v2'} v1 = info['k1'] # v1 v2 = info.get('k1') # v1 (經常使用此方法) v3 = info.get('k111',666) # 666 (不在字典範圍內則打印後面的內容) v4 = info.get('k111') # None
修改 (存在就修改/不存在就增長)
data = {11:22,33:44,55:66} data[11] = 99 print(data) # {11: 99, 33: 44, 55: 66} data[77] = 88 print(data) # {11: 22, 33: 44, 55: 66, 77: 88}
刪除 (del)
data = {11:22,33:44,55:66} del data[11] # 刪除了一個鍵值對 print(data) # {33:44,55:66}
pop 刪除
info = {'k1':'v1','k2':'v2'} result = info.pop('k2') #v2 print(info,result) #{'k1':'v1'} v2
update 批量添加
info = {'k1':'v1','k2':'v2'} #不存在就添加,存在就覆蓋 info.update({'k3':'v3','k4':'v4','k2':666}) print(info) # {'k1': 'v1', 'k2': 666, 'k3': 'v3', 'k4': 'v4'}
交集 (intersection)
a = {1,2,3,4,5,} b = {2,4,6,7} c = a.intersection(b) print(c) # {2, 4}
並集(union)
a = {1,2,3,4,5,} b = {2,4,6,7} c = a.union(b) print(c) # {1, 2, 3, 4, 5, 6, 7}
差集(difference)
a = {1,2,3,4,5} b = {2,4,6,7} c = a.difference(b) #{1,3,5} c = b.difference(a) #{6,7}
單個添加 ;add
a = {1,2,3,4,5} a.add(67) #只能添加單個元素 print(a) #{1, 2, 3, 4, 5, 67}
批量添加: update
v = {1,2,3,4,} v.update({5,6,7}) #後面的只能是集合/字典/元組/列表,不能是單獨的幾個元素 print(v) #{1,2,3,4,5,6,7}
刪除: discard
v = {1,2,45} v.discard(45) #刪除指定元素 print(v) #{1,2}
注意
#嵌套時 列表/字典/集合 不能做爲集合裏面的元素
len(計算長度) 均可以
索引 集合是無序的因此沒有,其他都有
切片 字典和集合沒有,其他都有
步長 字典和集合沒有,其他都有 " 經過步長能夠反轉字符串:[ : : -1 ]"
for 循環 均可以
刪除 字符串 / 元組 是不可變類型,因此不能刪除,其他都有
修改 字符串 / 元組 是不可變類型,因此不能刪除,其他都有
讀取: r (read):只能讀不能寫,文件不存在就報錯
#打開文件: object = open('某個文件',mode = 'r',encoding = '編碼') #讀取文件全部內容到內存: content = object.read() print(content) #讀取文件的全部內容到內存,並按照每一行進行分割到列表中。 content = object.readlines() print(content) # 讀取文件的第一行: content= object.readline() 此時光標在第一行的末端 #若是之後讀取一個特別大的文件 for line in object: #一行一行進行讀取 line = object.strip() #去除換行最後一個換行 print(line) #關閉內容: object.close()
read(): 所有讀到內存
read(1)
1表示一個字符
obj = open('某個txt文件',mode='r',encoding='utf-8') data = obj.read(1) # 1個字符 obj.close() print(data)
1表示一個字節(二進制中)
obj = open('某個txt文件',mode='rb') # b:二進制的意思 data = obj.read(1) # 1個字節 obj.close()
寫入:w (write): 只能寫不能讀(先清空文件),文件不存在就新建
#打開文件: object = open('某個文件或要新建的文件',mode = 'w',encoding = '編碼') #寫內容: object.write('xxx') #關閉文件: object.close()
write(字符串)
obj = open('某個txt文件或要新建的文件',mode='w',encoding='utf-8') obj.write('你好') obj.close()
write(二進制)
obj = open('某個文件或要新建的文件',mode='wb') # obj.write('你好'.encode('utf-8')) v = '你好'.encode('utf-8') obj.write(v) obj.close()
追加; a (append): 只能追加不能讀,不存在則新建
#打開文件: object = open ('某個txt文件或要新建的文件',mode = 'a',encoding = '編碼') #寫內容: object.append() #關閉文件 object.close()
seek(光標字節位置),不管模式是否帶b,都是按照字節進行處理。
obj = open('某個txt文件',mode='r',encoding='utf-8') obj.seek(3) # 跳轉到指定字節位置,讀取後面內容 data = obj.read() obj.close() print(data) obj = open('a.txt',mode='rb') obj.seek(3) # 跳轉到指定字節位置 data = obj.read() obj.close() print(data)
tell(), 獲取光標當前所在的字節位置
obj = open('a.txt',mode='rb') obj.read() data = obj.tell() print(data) obj.close()
flush,強制將內存中的數據寫入到硬盤
v = open('a.txt',mode='a',encoding='utf-8') while True: val = input('請輸入:') v.write(val) v.flush() v.close()
v = open('a.txt',mode='a',encoding='utf-8') v.close()
with open('a.txt',mode='a',encoding='utf-8') as v: data = v.read() # 縮進中的代碼執行完畢後,自動關閉文件
with open('a.txt',mode='r',encoding='utf-8') as f1: data = f1.read() new_data = data.replace('飛灑','666') with open('a.txt',mode='w',encoding='utf-8') as f1: data = f1.write(new_data)
大文件修改
f1 = open('a.txt',mode='r',encoding='utf-8') f2 = open('b.txt',mode='w',encoding='utf-8') #先打開兩個文件,再進行操做 for line in f1: # 一行一行進行修改 new_line = line.replace('要被修改的內容','被修改後的內容') f2.write(new_line) f1.close() f2.close() #另外一種寫法: with open('a.txt',mode='r',encoding='utf-8') as f1, open('c.txt',mode='w',encoding='utf-8') as f2: for line in f1: new_line = line.replace('要被修改的內容','被修改後的內容') f2.write(new_line)
v = 前面 if 條件 else 後面 if 條件: v = '前面' else: v = '後面'
目前:面向過程編程 [可讀性差/可重複性差]
函數式編程
函數的基本結構
#函數的定義 def 函數名(參數): #函數內容 #函數的執行 函數名(參數)
示例: def get_list_first_data(): v = [11,22,33,44] print(v[0]) get_list_first_data() #注意:函數若是不被調用,則內部代碼永遠不會執行
參數
定義一個函數:給了函數一個名稱,指定了函數裏包含的參數,和代碼塊結構。 這個函數的基本結構完成之後,你能夠經過另外一個函數調用執行,也能夠直接從 Python 命令提示符執行。
示例:打印某個列表的元素 def get_list_first_data(aaa): # aaa叫形式參數(形參) v = [11,22,33,44] print(v[aaa]) get_list_first_data(1) # 調用函數時傳遞叫:實際參數(實參)
返回值
''' 函數沒有返回值,默認返回 None 函數執行過程當中遇到return,則終止,下面代碼永遠不會執行 能夠返回任意類型 '''
須要一個變量去接收
示例: # 讓用戶輸入一段字符串,計算字符串中有多少A字符的個數。有多少個就在文件a.txt中寫多少個「嘻嘻嘻」。 def get_char_count(data): sum_counter = 0 for i in data: if i == 'A': sum_counter += 1 return sum_counter def write_file(line): if len(line) == 0: return False # 函數執行過程當中,一旦遇到return,則中止函數的執行。 with open('a.txt',mode='w',encoding='utf-8') as f: f.write(line) return True content = input('請輸入:') counter = get_char_count(content) write_data = "嘻嘻嘻" * counter status = write_file(write_data) if status: print('寫入成功') else: print('寫入失敗')
位置參數 : (調用函數並傳入函數)
關鍵字傳參:
def func(num1,num2) print(num1,num2) func(num1=1,num2=2)
位置傳參和關鍵字傳參能夠混合使用: ######## 位置傳參必定要在關鍵字傳參前面 ###########
默認參數 (默認參數推薦用不可變類型,慎用可變類型)
def func(a1,a2,a3=1,a4=2) print(a1,a2,a3,a4) func(11,22) #a3和a4 已有默認參數,因此沒必要再定義參數 func(11,22,a3=10,a4=100) #再次定義參數,覆蓋前面的參數
當默認參數數可變類型時
#注意一 def func(a,b=[]): b.append(a) return b v1 = func(1) v2 = func(2,[11,22]) v3 = func(3) print(v1,v2,v3) #[1,3] [11,22,2] [1,3] #注意二: def func(a,b=[]): b.append(a) print(b) func(1) #[1] func(2,[11,22]) #[11,22,2] func(3) #[1,3]
萬能參數(打散)
*args:能夠接收任意個數的位置參數,並將其轉換爲元組
調用函數無*
def func(*args): print(args) func(1,2,3) #打印func後內容,裏面能夠是列表集合等
調用函數有*
def func(*args): print(args) func(*(1,2,3,4)) # 無論裏面的內容是列表/集合都打印成元組,當裏面內容爲字典時,打印內容爲字典的key(鍵)
**kwargs : 能夠接收任意個數的關鍵字參數,並將其轉換爲字典
調用函數無**
def func(**kwages): print(kwages) func(k1=1,k2=2) #{'k1': 1, 'k2': 2}
調用函數有**
def func(**kwages): print(kwages) func(**{'k1':1,'k2':2}) #後面內容只能是字典
僅限關鍵字參數
def func(a,b,*args,c): print(a,b) print(c) func(1,2,3,4.c=222) 打印:1,2 222
*的做用
a,b,*c = (1,2,3,4,5,6,7) print(a,b,c) # 1 2 [3,4,5,6,7] a,*b,c = [11,22,33,44,55,66,77] print(a,b,c) # 11 [22, 33, 44, 55, 66] 77 a,*b,c = range(10) print(a,b,c) # 0 [1, 2, 3, 4, 5, 6, 7, 8] 9
python中
py文件 : 全局做用域
函數 : 局部做用域
做用域查找數據規則 : 優先在本身的做用域查找數據,本身沒有再去上一級查找,而後上上級,直到全局,全局沒有就報錯
#示例1: x = 10 def func(): x = 8 print(x) # 8 def x1(): print(x) # 9 x = 9 x1() x = 10 print(x) # 10 func() #示例2: x = 10 def func(): x = 8 print(x) # 8 def x1(): print(x) # 8 x1() x = 9 x1() # 9 x = 10 print(x) # 10 func()
子做用域中只能找到父級中的值,默認沒法從新爲父級中的變量進行賦值. (globol / nonlocal 能夠強制作)
global : 找到並改變全局中的變量
# 示例 name = "老男孩" def func(): name = 'alex' def inner(): global name name = 999 inner() print(name) # 'alex' func() print(name) # 999
# 聲明全局中存在這個變量 def func(): global name nmae = 'alex' func() print(name) # alex
nonlocal : 找到並改變上一級中的變量
#示例: name = "老男孩" def func(): name = 'alex' def inner(): nonlocal name name = 999 inner() print(name) # 999 func() print(name) # "老男孩"
補充:
全局變量之後必須所有是大寫
USER_LIST = [11,22,3] def func(): name = 'asdf' USER_LIST.append(12) USER_LIST.append(name) func() print(USER_LIST)
函數名當作變量來使用:
def func(): print(123) v1 = func #指向的是同一內存地址 v1()
#注意:不帶括號指向的是內存地址,帶括號是調用函數 def func(): return 123 func_list1 = [func,func,func] func_list2 = [func(),func(),func()] print(func_list1) # 打印的是內存地址 print(func_list2) #打印的是 : [123,123,123] 調用函數 info = { 'k1':func, #內存地址 'k2':func(), # 調用函數 } print(info)
函數能夠當作參數進行傳遞
結果爲: 666 none none
用於表示簡單的函數
注意:列表全部方法的返回值基本都爲none,字符串全部方法的返回值基本都返回新值
其餘:
len / open / id / range / type /
all 可迭代對象中所有是true 纔是true
l1 = [1,'alex','',0] print(all(l1)) # false
any 可迭代對象中有一個爲true就是true
l1 = [0,'',1,'alex'] print(any(l1)) # true
repr 返回一個對像的string形式
s1 = 'alex' print(s1) # alex print(repr(si)) # 'alex'
zip 拉鍊方式
lis = [1,2,3,4,5] tu = ('a','b','c') s1 = 'alex' obj = zip(lis,tu,s1) print(obj) # 獲得是一個迭代器 print(list(obj)) # [(1, 'a', 'a'), (2, 'b', 'l'), (3, 'c', 'e')]
輸入輸出 :
print / input
print(1,2,3,4,sep = '-') # 1-2-3-4
強制轉換
dict / list / tuple / int / str / bool / set
dict 建立字典的幾種方式
直接建立
元組的解構
dic1 = dict([(1,'one'),(2,'two'),(3,'three')]) dic2 = dict(one=1,two=2) print(dic1) # {1: 'one', 2: 'two', 3: 'three'} print(dic2) # {'one': 1, 'two': 2}
reversed 返回的是一個翻轉的迭代器
l = [i for i in range(10)] obj = reversed(l) print(obj) # 獲得的的是一個迭代器 print(l) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] print(list(obj)) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
編碼相關
Chr , 將十進制數字轉換成Unicode編碼中的對應字符串
v = char(99) print(v) # c
ord , 根據字符在Unicode編碼中找到其對應的十進制
con = ord('中國') print(con) # 20013
數學相關
abs() 絕對值
float() 轉換爲浮點型(小數)
max() 找到最大值
sum() 求和
round() 返回浮點數x的四捨五入值
print(round(12.238,2)) #12.24 print(round(12.234,2)) # 12.23
pow() 求一個數的冪
v = pow(2,3) print(v) # 2**3 = 8
divmod() 兩數相除的商和餘數
a,b = divmod(103,5) print(a,b) # a=20 b=3
# 經過分頁對數據進行展現 """ 要求: 每頁顯示10條數據 讓用戶輸入要查看的頁面:頁碼 """ USER_LIST = [] for i in range(1,836): temp = {'name':'啦啦啦-%s' %i,'email':'123%s@qq.com' %i } USER_LIST.append(temp) # 數據總條數 total_count = len(USER_LIST) # 每頁顯示10條 per_page_count= 10 # 總頁碼數 max_page_num,a = divmod(total_count,per_page_count) if a>0: max_page_num += 1 while True: pager = int(input('要查看第幾頁:')) if pager < 1 or pager > max_page_num: print('頁碼不合法,必須是 1 ~ %s' %max_page_num ) else: """ # 第1頁:USER_LIST[0:10] -> 0123456789 # 第2頁:USER_LIST[10:20] # 第3頁:USER_LIST[20:30] """ start = (pager-1) * per_page_count end = pager * per_page_count data = USER_LIST[start:end] for item in data: print(item)
進制轉換相關
bin() 將十進制轉換成二進制
oct() 將十進制轉換爲八進制
hex() 將十進制轉換爲十六進制
int() 將其餘進制轉換爲十進制
# 二進制轉化成十進制 v1 = '0b1101' result = int(v1,base=2) print(result) # 八進制轉化成十進制 v1 = '0o1101' result = int(v1,base=8) print(result) # 十六進制轉化成十進制 v1 = '0x1101' result = int(v1,base=16) print(result)
#請將 ip = "192.168.12.79" 中的每一個十進制數轉換成二進制: # 0010100100001010010001010010001010010 -> 十進制的值 ip = "192.168.12.79" ip_list = ip.split('.') lis = [] for i in ip_list: data = bin(int(i)) con = data.replace(data[:2],'0'*(8-len(data[2:]))) lis.append(con) mes = ''.join(lis) result = int(mes,base = 2) print(result)
括號內帶 key
sorted 排序
l1 = [22, 33, 1, 2, 8, 7,6,5] l2 = sorted(l1) print(l2) # [1, 2, 5, 6, 7, 8, 22, 33] l2 = [('大壯', 76), ('雪飛', 70), ('納欽', 94), ('張珵', 98), ('b哥',96)] print(sorted(l2,key= lambda x:x[1])) # 返回的是一個列表,默認從低到高 # [('雪飛', 70), ('大壯', 76), ('納欽', 94), ('b哥', 96), ('張珵', 98)] print(sorted(l2,key= lambda x:x[1],reverse=True)) # 從高到低 # [('張珵', 98), ('b哥', 96), ('納欽', 94), ('大壯', 76), ('雪飛', 70)]
min 取最小值 (max的用法同樣)
# 示例1: 以絕對值的方式取最小值: l1 = [33, 2, 3, 54, 7, -1, -9] print(min(l1,key = abs) # 1 # 示例2: dic = {'a': 3, 'b': 2, 'c': 1} print(min(dic)) # min 會默認按照字典的鍵去比較 # 結果獲得 a (按照ASCII碼對照表的大小) print(min(dic,key = lambda a: dic[a])) # c print(min(dic.values(),key=lambda x:x)) # 1
總結:凡是能夠加key的,它會自動的將可迭代的對象中的每一個元素按照順序傳入key對應的函數中,返回的是循環的那個元素
經過list取值的內置函數
map : 循環每一個元素(第二個參數),而後讓每一個元素執行函數(第一個參數),將每一個函數執行的結果保存到新的列表中,並返回.(至關於列表推導式的循環模式)
v1 = [11,22,33,44] result = map(lambda x:x+100,v1) #將列表裏元素每一個都加上100 print(list(result)) # 特殊
filter : 篩選(至關於列表推導式的篩選模式)
v1 = [11,22,33,'asd',44,'xf'] def func(x): if type(x) == int: return True return False result = filter(func,v1) print(list(result)) # [11, 22, 33, 44] #也可簡寫成以下: result = filter(lambda x: True if type(x) == int else False ,v1) print(list(result)) # 或 result = filter(lambda x: type(x) == int ,v1) print(list(result)) # 示例二: ret = ['1', '2', '60', '', '5', '4', '3','',''] ret = filter(lambda n:n,ret) print(list(ret)) # 出除了列表裏的空字符串,並無改變裏面元素的位置
reduce : 將多個元素變成一個元素
import functools #導入一個模塊 v1 = ['wo','hao','e'] def func(x,y): return x+y result = functools.reduce(func,v1) print(result) result = functools.reduce(lambda x,y:x+y,v1) print(result)
函數能夠做爲返回值
面試題相關:
閉包
什麼是閉包:
遞歸 :
#遞歸打印斐波那契數 def func(a,b): # 1 # 1 # 2 # 3 # 5 print(b) func(b,a+b) func(0,1)
裝飾器編寫的格式
def 外層函數(參數) def 內層函數(*args,**kwargs) #函數執行以前 data= 參數(*args,**kwags) #函數執行以後 return data return 內層函數
應用
def func(arg): def inner(): v = arg() return v return inner # 第一步:執行func函數並將下面的函數當作參數進行傳遞, 至關於:func(index) # 第二步: 將func返回的值從新賦值給下面的函數名 index = func(index) @func def index(): print(123) return 666 ret = index() print(ret) # 先打印 123 ,在打印 666
#示例:計算函數執行時間 import time def base(func): def inner(): start_time = time.time() --->#函數執行以前 v= func() end_tme = time.time() ---->#函數執行以後 print(end_time-start_time) return v return inner @base def func1(): time.sleep(2) # 函數執行延緩2秒 print(123) func1() @base def func2(): time.sleep(1) print(456) func2()
關於返回值
def x1(func): def inner(*args,**kwargs): data = func(*args,**kwargs) return data return inner #func函數帶括號,執行 f1 函數,先打印'123',先將666返回給data,data再返回給v1 @x1 def f1(): print(123) return 666 v1 = f1() # 獲得的是inner函數的返回值 print(v1)
關於先後
def base(func): def inner(*args,**kwargs): print('函數調用以前') data = func(*args,**kwargs) #執行原函數並獲取返回值 print('調用原函數以後') return data return inner @base def index(): print(123) ret= index() print(ret) # None
帶參數的裝飾器
基本格式
def base(counter): def wrapper(func): def inner(*args,**kwargs): data = func(*args,**kwargs) # 執行原函數並獲取返回值 return data return inner return wrapper @base(9) def index(): pass #先執行base函數,而後將返回值wrapper返回,變成不帶參數的裝飾器
面試相關
#寫一個帶參數的函,實現:參數是多少,被裝飾的函數就要執行多少次,返回最後一次執行的結果 def base(counter): def wrapper(func): def inner(*args,**kwargs): for i in range(counter): data = func(*args,**kwargs) # 執行原函數並獲取返回值 return data return inner return wrapper @base(5) def index(): return 8 v = index() print(v)
列表推導式(也叫列表生成式)
用一行代碼構建一個比較複雜有規律的列表
基本格式
v1 = [i for i in 可迭代對象] v2 = [i for i in 可迭代對象 if 條件]#條件爲true才進行append
#示例 v1 = [99 if i>5 else 66 for i in range(10)] v2 = [lambda : 100 for i in range(10)] result = v2[9]() # 100 v3 = [lambda :i for i in range(10)] result = v3[5]() # 9 v4 = [lambda x:x*i for i in range(10)] # 新浪微博面試題 # 1.請問 v4 是什麼? 函數地址 # 2.請問 v4[0](2) 的結果是什麼? 18 def num(): return [lambda x:i*x for i in range(4)] # num() -> [函數,函數,函數,函數] print([ m(2) for m in num() ]) # [6,6,6,6]
集合推導式
v1 = { i for i in 'alex' }
字典推導式
v1 = { 'k'+str(i):i for i in range(10) }
生成器推導式:
# def func(): # result = [] # for i in range(10): # result.append(i) # return result # v1 = func() v1 = [i for i in range(10)] # 列表推導式,當即循環建立全部元素。 print(v1) # def func(): # for i in range(10): # yield i # v2 = func() v2 = (i for i in range(10)) # 生成器推導式(非元組推導式),建立了一個生成器,內部循環爲執行。
__init__
.py文件內置模塊
第三方模塊 :
1.找到python所在的根目錄-->再找到Scripts目錄-->最後找到pip.exe 2.把pip.exe所在的目錄添加到環境變量中 3.pip install 要安裝的模塊名稱 #pip install xlrd #安裝完成後,若是導入不成功 - 重啓pycharm - 安裝錯了
自定義模塊
本身寫一個模塊(一個py文件): aaa.py
def f1(): prinrt('f1') def f2(): print('f2')
在另外一個py文件中調用模塊中的功能 :a1.py
#調自定義模塊中的功能 import aaa aaa.f1() aaa.f2()
運行
a1.py
什麼是模塊
什麼是包
__init__
.py文件中的內容示例: # xxx.py def show(): print('nihao') def func(): pass print(111)
#導入模塊,加載此模塊中的全部值到內存(一) import xxx print(222) ##調用模塊中的函數 xxx.func()
#導入模塊(二) from xxx import func,show from xxx import func from xxx import * func()
#導入模塊(三) from xxx import func as f #起別名 def func(): print(222) f()
示例二:
xxxxxx #(某個文件夾) -jd.py #裏面有個f1函數 -tb.py -pdd.py
import xxxxxx.jd jd.f1()
from xxxxxx import jd jd.f1()
from xxxxxx.jd import f1 f1()
導入一個包(文件夾)至關於執行了這個包下的__init__
文件,並不至關於把這個包下的全部文件都導入進來了
import random def get_random_code(length = 6): data = [] for i in range(length): v = random.randint(65,90) data.append(chr(v)) return ''.join(data) code = get_random_code() print(code)
import random # 導入一個模塊 v = random.randint(起始,終止) #獲得一個隨機數
random.unifrom
import random a = random.unifrom(3,5) print(a) # 返回的是3-5之間的一個浮點數
random.random
print(random.random()) #獲得是一個0-1之間的浮點數
做用: ,密文登入驗證 / 檢驗文件的一致性
用於加密相關的操做,把一個大的數據切分紅不一樣塊,分別對不一樣的塊進行加密彙總的結果,和直接對總體數據加密的結果是一致的
將bytes類型字節轉化成固定長度的16進制數字組成的字符串
不一樣的bytes利用相同的算法轉化的結果必定不一樣
相同的bytes利用相同的算法轉化的結果必定相同
haslhib 算法不可逆
將指定的'字符串'進行加密
import hashlib def get_md5(num): obj = hashlib.md5() # 獲取一個加密對象 obj.update(num.encode('utf-8')) # 使用加密對象的update進行加密 return obj.hexdigest() # 經過hexdigest獲取加密效果 val = get_md5('某段數字') print(val)
加鹽 : (讓密碼更加安全)
import hashlib def get_md5(data): # md5括號內的內容越長,越不容易被破解 obj = hashlib.md5("sidrsicxwersdfsaersdfsdfresdy54436jgfdsjdxff123ad".encode('utf-8')) obj.update(data.encode('utf-8')) result = obj.hexdigest() return result val = get_md5('123') print(val)
應用
import hashlib USER_LIST = [] def get_md5(data): obj = hashlib.md5("12:;idrsicxwersdfsaersdfsdfresdy54436jgfdsjdxff123ad".encode('utf-8')) obj.update(data.encode('utf-8')) result = obj.hexdigest() return result def register(): print('**************用戶註冊**************') while True: user = input('請輸入用戶名:') if user == 'N': return pwd = input('請輸入密碼:') temp = {'username':user,'password':get_md5(pwd)} USER_LIST.append(temp) def login(): print('**************用戶登錄**************') user = input('請輸入用戶名:') pwd = input('請輸入密碼:') for item in USER_LIST: if item['username'] == user and item['password'] == get_md5(pwd): return True register() result = login() if result: print('登錄成功') else: print('登錄失敗')
密碼 不顯示,(只能在終端運行)
import getpass pwd = getpass.getpass('請輸入密碼') if pwd == '123' print('輸入正確')
sys.getrefcount : 獲取一個值的應用計數
import sys #導入模塊 a = [1,2,3] b = a print(sys.getrefcount(a)) #結果爲:3 至關於a被使用了三次
sys.getrecursionlimit : python中默認支持的遞歸數量
import sys print(sys.getrecursionlimit()) # 結果爲 :1000 修改最大遞歸次數: import sys sys.setrecursionlimit(10000)
sys.stdout.write 相似於print打印
\n 換行
\t 製表符
\r 回到當前行的起始位置
print('1231你好你好你好23\r',end='') print('你好',end='') #因爲\r的存在,回到了當前行的起始位置,沒有換行,只會打印'你好'
sys.argv : 命令行參數,第一個元素是程序自己路徑
#示例: import sys if len(sys.argv) < 3: print('參數不夠,請從新運行') else: file_path = sys.argv[1] content = sys.argv[2] with open(file_path,mode='w',encoding='utf-8') as f: f.write(content)
sys.path 會自動將當前目錄的路徑添加到sys.path列表中
# 若是想要引用自定義的模塊,要麼將這個模塊放在當前目錄下面,要麼手動添加到sys.path中 ''' sys.path 列表中的第一個元素老是當前執行腳本的父目錄 '''
sys.modules 查看導入了那些模塊
os.path.exists(path) , 若是path存在,返回True;若是path不存在,返回False
os.path.getsize() 獲取文件的大小
a = os.path.getsize(r'D:\python全棧\網絡編程\day28\one\server.py') print(a) # 693
os.path.abspath() : 獲取一個文件的絕對路徑
path = '某個須要查看路徑的文件' import os v1 = os.path.abspath(path) print(v1)
os.path.dirname : 獲取路徑的上級目錄(不判斷路徑是否存在)
import os v = r"C:\python36\新建文件夾\python36.exe D:/第三週/day14.py" print(os.path.dirname(v)) #C:\python36\新建文件夾\python36.exe D:/第三週 一級一級往上走
os.path.split 把路徑中的路徑名和文件名切分開,結果是元組
import os res = os.path.split(r'd:/aaa/bbb/ccc/a.txt') print(res) # ('d:/aaa/bbb/ccc', 'a.txt')
os.path.join : 路徑的拼接
import os path = "C:\python36\新建文件夾\python36.exe" v = 'n.txt' result = os.path.join(path,v) print(result) #C:\python36\新建文件夾\python36.exe \n.txt result = os.path.join(path,'n1','n2','n3') print(result) #C:\python36\新建文件夾\python36.exe \n1\n2\n3
os.listdir :查看一個目錄下全部的文件(第一層)
import os result = os.listdir(r'D:\untitled') for i in result: print(i)
os.walk : 查看一個目錄下全部的文件(全部層)
import os result = os.walk(r'D:\untitled') for a,b,c in result: # a,正在查看的目錄 b,此目錄下的文件夾 c,此目錄下的文件 for item in c: path = os.path.join(a,item) print(path)
os.path.basename() :獲取文件名稱
返回path最後的文件名,若是path以 / 結尾,就返回空值 a = os.path.basename(r'D:\python全棧\網絡編程\day28\four') print(a) # 結果爲: four a = os.path.basename('D:\python全棧\網絡編程\day28\four/') print(a) # 結果:啥都沒有,空
v1 = r"D:\code\s21day14\n1.mp4" (推薦) print(v1) # D:\code\s21day14\n1.mp4 v2 = "D:\\code\\s21day14\\n1.mp4" (不推薦) print(v2) # D:\code\s21day14\n1.mp4
os.makedirs 建立目錄和子目錄
os.rename 重命名
import os os.rename('某個文件的名字','想要修改後的名字')
#練習: import os #1.讀取文件大小(字節) file_size = os.stat('某個文件').st_size #2. 一點一點讀取文件 read_size = 0 with open('某個文件',mode='rb') as f1,open('將要寫入的文件',mode='wb') as f2: while read_size < file_size: chunk = f1.read(1024) #每次最多去讀取1024字節 f2.write(chunk) read_size += len(chunk) val = int(read_size / file_size * 100) #查看打印進度 print('%s%%\r' %val ,end='')
刪除
# 刪除文件 os.remove('文件名') # 刪除目錄(必須是空目錄) os.removedirs('目錄名')
os.getcwd 查看工做目錄
os.chdir 改變工做目錄
os.urandom(16) 獲取一個隨機的16字節大小的字符串
# 和執行操做系統命令相關 os.popen/os.system import os os.system('dir') ret = os.popen('dir') print(ret.read())
序列化:將內存中的數據轉換成字符串,用以保存文件或經過網絡傳輸
反序列化:從文件或網絡中獲取的數據轉換成內存中原來的數據類型
json : 一個特殊的字符串 [長得像列表/字典/字符串/數字/真假]
import json #序列化:將python的值轉換爲json格式的字符串 v = [11,22,{'k1':'v1'},True,'ggg'] v1 = json.dumps(v) print(v1) #"[11, 22, {"k1": "v1"}, true, "ggg"]" #反序列化 : 將json格式的字符串轉換成python的數據類型 v2 = '["alex",123]' print(type(v2)) #字符串類型 v3 = json.loads(v2) print(v3,type(v3)) #['alex', 123] <class 'list'>
字典或列表中若有中文,序列化時想要保留中文顯示
v = {'k1':'alex','k2':'李傑'} import json val = json.dumps(v,ensure_ascii=False) print(val)
注意:
# 將json類型的結果寫到文件中 import json with open('a.txt',mode='w',encoding='utf-8') as f: json.dumps([1,2,3],f,ensure_ascii=False) # 從文件中讀取json類型結果 with open('a.txt',mode='r',encoding='utf-8') as f: con = json.loads(f) print(con)
# 把須要序列化的對象.經過屢次序列化的方式, 用文件的write方法,把屢次序列化後的json字符串,寫到文件中. with open('b.txt',mode='at',encoding='utf-8') as f: f.write(json.dumps([1,2,3]) + '\n') f.write(json.dumps([4,5,5]) + '\n') # 把分次序列化的json字符串,反序列化回來 with open('b.txt',mode='rt',encoding='utf-8') as f: for x in f: print(json.loads(x.strip()))
pickle:優勢:python中全部的東西都能被他序列化(轉換爲bytes類型) 缺點:序列化的內容只有python認識
dumps loads 只能用於網絡傳輸
l1 = [1, 2, 3] import pickle st = pickle.dumps(l1) print(st) # b'\x80\x03]q\x00(K\x01K\x02K\x03e.' l2 = pickle.loads(st) print(l2,type(l2)) # [1, 2, 3] <class 'list'>
dump load 直接寫入文件(還能夠寫入函數名,對象)
刪除目錄
import shutil shutil.rmtree('要刪除的目錄')
重命名
import shutil shutil.move('原目錄','修改後的目錄')
壓縮文件 shutil.make_archive
import shutil shutil.make_archive('要壓縮的文件','文件的後綴名(如zip)','要壓縮到的路徑') #示例: import shutil shutil.make_archive('xxx','zip','D:\第三週')
解壓文件 shutil.unpack_archive
import shutil shutil.unpack_archive('要解壓的文件',extract_dir=r'D:\code\xxxxxx\xxxx',format='zip')
示例: import os import shutil from datetime import datetime ctime = datetime.now().strftime('%Y-%m-%d %H-%M-%S') # 1.壓縮lizhongwei文件夾 zip # 2.放到到 code 目錄(默認不存在) # 3.將文件解壓到D:\x1目錄中。 if not os.path.exists('code'): #判斷路徑是否存在 os.makedirs('code') shutil.make_archive(os.path.join('code',ctime),'zip','D:\code\s21day16\lizhongwei') #壓縮文件 file_path = os.path.join('code',ctime) + '.zip' #兩個路徑拼接 shutil.unpack_archive(file_path,r'D:\x1','zip') #解壓文件
拷貝文件
shutil.copy2('原文件', '現文件')
拷貝目錄
shutil.copytree("原目錄", "新目錄", ignore=shutil.ignore_patterns("*.pyc")) # ignore後面是不拷貝的內容
獲取磁盤使用空間
total, used, free = shutil.disk_usage(".") print("當前磁盤共: %iGB, 已使用: %iGB, 剩餘: %iGB"%(total / 1073741824, used / 1073741824, free / 1073741824))
time :
import time now = time.localtime() print(now) print(now.tm_year) # 獲取當前時間的年份 print(now.tm_mon) # 獲取當前時間的月份 print(now.tm_mday) # 獲取當前時間的幾號
datetime
獲取datetime格式時間
import time from datetime import datetime,timezone,timedelta v1 = datetime.now() # 獲取當前本地時間 print(v1) # 2019-04-18 16:39:31.802269 tz = timezone(timedelta(hours=7)) #當前東7區時間 (如要獲取西7區時間 hours=-7) v2 = datetime.now(tz) print(v2) #2019-04-18 15:39:31.802269+07:00 (中國在東8區,因此慢一個小時) v3 = datetime.utcnow() #當前UTC時間(世界時間) print(v3) #2019-04-18 08:39:31.802269 (比中國時間慢8個小時)
把datetime格式轉換成字符串 (strftime)
import time from datetime import datetime,timezone,timedelta v1 = datetime.now() val = v1.strftime("%Y-%m-%d %H:%M:%S") #(年-月-日 時:分:秒) print(val) #2019-04-18 16:48:29
字符串轉成datetime格式 datetime.strptime
import time from datetime import datetime,timezone,timedelta v1 = datetime.strptime('2019-4-18','%Y-%m-%d') print(v1,type(v1)) # 2019-04-18 00:00:00 <class 'datetime.datetime'>
datetime時間的加減
from datetime import datetime,timedelta v1 = datetime.strptime('2008-08-08','%Y-%m-%d') v2 = v1-timedelta(days=150) data = v2.strftime('%Y-%m-%d') print(data) #2008-03-11 #先轉換爲datetime格式進行加減,而後轉換爲字符串格式打印出來
時間戳和datetime的關係
import time from datetime import datetime,timezone,timedelta ctime = time.time() print(ctime) # 1555578896.8276453 v1 = datetime.fromtimestamp(ctime) print(v1) # 2019-04-18 17:14:56.827645 v1 = datetime.now() val = v1.timestamp() print(val) #1555579030.002739
import requests # 獲取網頁源碼 ret = requests.get('一個網址 ').strip() # 輸入網址後加一個空格 print(ret.content) # 以字節的方式去顯示,中文顯示爲字符 print(ret.text) # 以文本的方式去顯示
示例: #寫函數去,接受一個列表。列表中都是url,請訪問每一個地址並獲取結果。 import requests def func(url_list): result = [] try: for url in url_list: response = requests.get(url) result.append(response.text) except Exception as e: pass return result #['http://www.baidu.com'] (中國沒法訪問谷歌) def func2(url_list): result = [] for url in url_list: try: response = requests.get(url) result.append(response.text) except Exception as e: pass return result #['http://www.baidu.com','http://www.bing.com'] func(['http://www.baidu.com','http://www.google.com','http://www.bing.com'])
__next__
方法且每次調用都獲取可迭代對象中的元素__iter__
()__next__
()#示例: v1 = "alex" v2 = iter(v1) while True: try: val = v2.__next__() print(val) except StopIteration as e: break
直到報錯:StopIteration錯誤,表示迭代已經完畢
如何判斷一個對象是不是迭代器 : 內部是否有__next__
方法
for 循環
v1 = [11,22,33,44] # 1.內部會將v1轉換成迭代器 # 2.內部反覆執行 迭代器.__next__() # 3.取完不報錯 for item in v1: print(item)
可迭代對象
_iter__
方法且返回一個迭代器生成器 (函數的變異)
獲取生成器的三種方式
生成器的本質就是迭代器,
生成器函數 (內部是否包含yield)
def func(): print('F1') yield 1 print('F2') yield 2 print('F3') #函數內部代碼不會執行,返回一個生成器對象 v1 = func() #生成器能夠被for 循環,一旦開始循環函數內部代碼就開始執行 for item in v1: print(item) # F1 1 F2 2 F3
# yield from 優化了內層循環,提升了效率 def func(): l1 = [1, 2, 3, 4, 5] yield from l1 ret = func() print(next(ret)) # 取列表裏的一個元素 1 # yield def func(): l1 = [1, 2, 3, 4, 5] yield l1 ret = func() print(next(ret)) #獲得的是一個列表
總結:
__init__
,把空間的內存地址做爲self參數傳遞到函數內部__init__
中的邏輯以後,self變量會自動的被返回到調用處(發生實例化的地方)應用場景:
基本格式
class Person: def __init__(self,name,sex,job,age): self.name = name self.sex = sex self.job = job self.age = age obj = Person('alex','nan','IT','30') # 實例化一個obj對象 print(obj.__dict__) # {'name': 'alex', 'sex': 'nan', 'job': 'IT', 'age': '30'} obj.name = 'wusir' # 修改屬性 obj.money = 1000 # 增長屬性 del obj.money # 刪除屬性
組合:
一個類的對象是另外一個類對象的屬性
# 查看linux57期的班級所學課程的價格 # 查看python22期的班級所學課程的週期 class Clas: def __init__(self,cname,begint,teacher,course): self.cname = cname self.begint = begint self.teacher = teacher self.course = course class Course: def __init__(self,name,period,price): self.name = name self.period = period self.price = price python = Course('python','6 months',21800) linux = Course('linux','5 months',19800) py22 = Clas('python全棧22期','2019-4-26','小白',python) linux57 = Clas('linux運維57期','2019-3-27','李導',linux) print(py22.course.period) print(linux57.course.price)
對象的做用
存儲一些值,之後方便本身使用
class File: def read(self): with open(self.xxx,mode= 'r',encoding = 'utf-8') as f: data = f.read() return data #實例化一個File 類的對象 obj1 = File() #在對象中寫一個xxx = 'text.log' obj1.xxx = 'text.log' #經過對象調用類中的read方法,read方法中的self就是obj obj.read()
總結:將數據封裝到對象,方便使用
總結:若是寫代碼時,函數比較多而亂
1.能夠將函數歸類並放到同一類中
2.函數若是有一個反覆使用的公共值,則能夠放到對象中
練習
#循環讓用戶輸入用戶名/密碼/郵箱.輸入完成後再進行打印 class Person: def __init__(self,user,pwd,email): self.username = user self.password = pwd self.email = email user_lisr = [] while Ture: user = input('輸入用戶名') pwd = input('請輸入密碼') email = input('請輸入郵箱') a = Person(user,pwd,email) user_list.append(a) for item in USER_LIST: temp = "個人名字:%s,密碼:%s,郵箱%s" %(item.username,item.password,item.email,) print(temp)
# 父類(基類) class Base: def f1(self): pass # 子類(派生類) class Foo(Base): def f2(self): pass # 建立一個子類的對象 obj = Foo() # 執行對象.方法時,優先在本身的類中找,若是沒有就是父類中找。 obj.f2() obj.f1() # 建立了一個父類的對象 obj = Base() obj.f1()
繼承方法中的查找方法的順序
父類和子類方法的選擇
繼承的其餘現象
多態:一個類表現出的多種形態,其實是經過繼承來完成的
''' 若是狗類繼承動物類,貓類也繼承動物類 那麼貓的對象也是動物類型的,狗的對象也是動物類型的 在這個例子中,動物這個類型表現出了貓和狗的形態 '''
# Python def func(arg): v = arg[-1] # arg.append(9) print(v)
廣義:把屬性的方法封裝起來,外面就不能直接調用了,要經過類的名字來調用
狹義: 把屬性和方法藏起來,外面不能調用,只能在內部偷偷調用
class User: def __init__(self,name,pwd): self.name = name self.__pwd = pwd # 私有的實例變量 / 私有的對象屬性 alex = User('alex',1234) print(alex.__pwd) # 沒法訪問 報錯 print(alex.pwd) # 報錯 ''' 給一個名字前面加上了雙下劃線的時候,這個名字就變成了一個私有的 全部私有的內容或者名字都不能再類的外部調用只能在類的內部使用 '''
# 從外部調用加雙下劃線的方法或靜態變量 class User: __country = 'china' # 私有的靜態變量 __name = 'Alex' def func(self): print(self.__name) # 在類的內部使用的時候,自動把當前這句話所在的類的名字拼在私有變量前完成變形 print(User._User__country) # china User().func() # Alex # __Country -->'_User__Country': 'China'
私有的內容不能被子類使用
其餘語言中的數據級別:
實例(對象)
類
類變量
####應用示例##### class Base: x = 1 obj.Base() print(obj.x) #先去對象中找,沒有再去類中找 1 obj.y = 123 #在對象中添加了一個y=123的變量 print(obj.y) #對象中y=123 123 obj.x = 123 #在對象中添加一個變量x=123 print(obj.x) # 123 print(Base.x) #類中x=1 1
方法(綁定方法)
定義:至少有一個self參數
執行:先建立對象, 對象.方法()執行
class Foo: def __init__(self): self.name = 111 def func(self,a,b) #綁定方法,至少有一個self參數 print(self.name,a,b) obj = Foo() obj.func(1,2)
靜態方法
定義
執行
class Foo: def __init__(self): self.name = 123 def func(self, a, b): print(self.name, a, b) @staticmethod def f1(): #靜態方法(能夠不用傳參數) print(123) obj = Foo() obj.func(1, 2) Foo.f1() obj.f1() # 不推薦
類方法
定義:
執行:
class Goods: __discount = 0.8 def __init__(self): self.__price = 5 self.price = self.__price * self.__discount @classmethod # 把一個對象的綁定方法修改爲一個類方法 def change_discount(cls,new_discount): cls.__discount = new_discount Goods.change_discount(0.6) # 類方法能夠經過類名來調用 obj1 = Goods() print(obj1.price) # 3.0 obj1.change_discount(0.5) # 類方法能夠經過對象來調用 obj2 = Goods() print(obj2.price) # 2.5 ############# 示例: import time class Date: def __init__(self,year,month,day): self.year = year self.month = month self.day = day @classmethod def today(cls): now_time = time.localtime() date = cls(now_time.tm_year,now_time.tm_mon,now_time.tm_mday) return date date = Date.today() print(date.year) print(date.month) print(date.day)
# 問題: @classmethod和@staticmethod的區別? ''' 一個是類方法,一個是靜態方法 定義: 類方法:用@classmethod作裝飾器且至少有一個cls參數 靜態方法:用@staticmethod作裝飾器且參數無限制 調用: 類.方法()直接調用 對象.方法()也可調用 (不推薦) '''
屬性
定義:
執行:
class Foo: @property def func(self): print(123) return 666 obj = Foo() result = obj.func print(result)
# property進階 class Goods: discount = 0.8 def __init__(self,name,origin_price): self.name = name self.__price = origin_price @property def price(self): return self.__price * self.discount @price.setter def price(self,new_value): if isinstance(new_value,int): self.__price = new_value apple = Goods('apple',5) print(apple.price) # 調用的是被@property裝飾的price apple.price = 10 # 調用的是被setter裝飾的price print(apple.price)
屬性的應用
''' 分頁並查看頁碼中的內容 ''' class Page: def __init__(self, total_count, current_page, per_page_count=10): self.total_count = total_count self.per_page_count = per_page_count self.current_page = current_page @property def start_index(self): return (self.current_page - 1) * self.per_page_count @property def end_index(self): return self.current_page * self.per_page_count USER_LIST = [] for i in range(321): USER_LIST.append('alex-%s' % (i,)) # 請實現分頁展現: current_page = int(input('請輸入要查看的頁碼:')) p = Page(321, current_page) data_list = USER_LIST[p.start_index:p.end_index] for item in data_list: print(item)
新式類 / 經典類
class Foo: pass class Foo(object): pass #在py3中這兩個的寫法是同樣的,由於全部的類默認都會繼承object類,所有都是新式類 # 若是在python2中這樣定義,則稱其爲:經典類 class Foo: pass # 若是在python2中這樣定義,則稱其爲:新式類 class Foo(object): pass ''' 新式類和經典類的區別: 新式類:繼承object ,有super mro ,繼承廣度優先 查看廣度優先的順序: 類名.mro() 經典類:不繼承object,沒有super mro ,繼承深度優先 '''
__init__
初始化方法
__new__
用於建立空對象(構建方法)
class A: def __new__(cls, *args, **kwargs): obj = super().__new__(cls) # obj = object.__new__(cls) # 第二種寫法 print('執行new方法') return obj # 須要將對象返回回去,才能執行init方法 def __init__(self): print('執行init方法') A() 先打印: 執行new方法 再打印: 執行init方法 # 實例化的時候: 先建立一個對象的空間,有一個指針指向類 --> __new__ 調用init --> __init__
__call__
對象加括號,執行cal方法
格式:
class A: def __call__(self, *args, **kwargs): print('*********') obj = A() print(callable(obj)) # 判斷對象是不是可被調用的,若是類中沒有call方法,則是False A()() # 對象加() 會自動執行call方法裏面的代碼 運行結果: True *********
__getitem__ __setitem__ __delitem__
class Foo(object): def __setitem__(self, key, value): print(key,value) def __getitem__(self, item): return item + 'uuu' def __delitem__(self, key): pass obj1 = Foo() obj1['k1'] = 123 # 內部會自動調用 __setitem__方法 #打印的結果爲 k1 123 val = obj1['xxx'] # 內部會自動調用 __getitem__方法 print(val) # 打印結果爲 xxxuuu del obj1['ttt'] # 內部會自動調用 __delitem__ 方法
__str__
和 __repr__
__str__
方法__str__
,就調用 __repr__
方法__repr__
不只僅是 __str__
的替代品,還有本身的功能__repr__
方法class clas: def __init__(self): self.student = [] def append(self,name): self.student.append(name) def __repr__(self): return str(self.student) def __str__(self): return 'aaa' py22 = clas() py22.append('大壯') print(py22) # aaa print(str(py22)) # aaa print('咱們py22班 %s'%py22) # 咱們py22班 aaa print('咱們py22班 %r'%py22) # 咱們py22班 ['大壯'] print(repr(py22)) # ['大壯']
__dict__
class Foo(object): def __init__(self,name,age,email): self.name = name self.age = age self.email = email obj = Foo('alex',19,'xxxx@qq.com') val = obj.__dict__ # 去對象中找到全部變量並將其轉換爲字典 print(val)
上下文管理
class Context: def __enter__(self): print('進入') return self def __exit__(self, exc_type, exc_val, exc_tb): print('推出') def do_something(self): print('內部執行') with Context() as ctx: print('內部執行') ctx.do_something() # 當語法有 with 類() 時,類裏面必須包含__enter__方法和__exit__方法;方法__enter__返回的是什麼,as後面接收就是什麼
__len__
class Cls: def __init__(self,name): self.name = name self.students = [] def len(self): return len(self.students) def __len__(self): return len(self.students) py22 = Cls('py22') py22.students.append('杜相璽') py22.students.append('莊博') py22.students.append('大壯') print(py22.len()) # 3 print(len(py22)) # 3 # py22.len() 調用的是def len # len(py22) 調用的是def __len__
__base__
查看類繼承了哪個類
兩個對象的相加
class Foo(object): def __add__(self, other): return 123 obj1 = Foo() obj2 = Foo() val = obj1 + obj2 print(val)obj1 = Foo() obj2 = Foo() val = obj1 + obj2 print(val)
__eq__
__gt__
__lt__
class Person(object): def __init__(self,name,age): self.name = name self.age = age def __eq__(self,other): # 兩個對象做比較的時候,會自動調用這個方法 print('in eq') def __gt__(self,other): print('in gt') def __lt__(self,other): print('in lt') alex = Person('alex',83) wusir = Person('wusir',74) alex == wusir # == 符號恰好會調用alex對象對應類的__eq__方法,wusir會被當作other參數傳入方法 alex < wusir # 執行__gt__方法 alex > wusir # 執行__lt__方法
特殊成員:就是爲了能快速實現執行某些方法而生
type:查看類型
class Foo: pass obj = Foo() if type(obj) == Foo: print('obj是Foo類的對象') # 判斷obj是不是foo的對象
issubclass 判斷是不是某個類的基類
class Base: pass class Base1(Base): pass class Foo(Base1): pass class Bar: pass print(issubclass(Bar,Base)) # false print(issubclass(Foo,Base)) # true
isinstance 判斷對象是不是某個類或其基類的實例對象
class Base(object): pass class Foo(Base): pass obj = Foo() print(isinstance(obj,Foo)) # 判斷obj是不是Foo類或其基類的實例(對象) # True print(isinstance(obj,Base)) # 判斷obj是不是Foo類或其基類的實例(對象) # True
super
class A(object): def func(self): print('A') class B(A): def func(self): super().func() print('B') class C(A): def func(self): super().func() print('C') class D(B,C): def func(self): super().func() super(D,self).func() print('D') D().func() # 結果: A C B D ''' super 是按照mro順序(D-->B-->C--A)來尋找當前類的下一個類 在D類中的super還能夠寫成: super(D,self).func(),py2中的新式類必須這樣寫 ''' # 示例: class User: def __init__(self,name): self.name = name class VIPUser(User): def __init__(self,name,level,strat_date,end_date): # User.__init__(self,name) super().__init__(name) # 推薦的 # super(VIPUser,self).__init__(name) self.level = level self.strat_date = strat_date self.end_date = end_date 太白 = VIPUser('太白',6,'2019-01-01','2020-01-01') print(太白.__dict__)
基本格式
try: pass except Exception as e: # Exception : 全部報錯信息都能接收 pass
finally:
try: int('asdf') except Exception as e: print(e) # e是Exception類的對象,中有一個錯誤信息。 finally: print('最後不管對錯都會執行') # #################### 特殊狀況 ######################### def func(): try: # v = 1 # return 123 int('asdf') except Exception as e: print(e) # e是Exception類的對象,中有一個錯誤信息。 return 123 finally: print('最後') func() #函數中有return時,finally也會執行
主動觸發異常
try: int('123') raise Exception('xxxxx') # 代碼中主動拋出異常 except Exception as e: print(e) # 打印的結果是Exception括號內拋出的異常
自定義異常
class MyException(Exception): pass try: raise MyException('asdf') except MyException as e: print(e)
class MyException(Exception): def __init__(self,message): super().__init__() self.message = message try: raise MyException('asdf') except MyException as e: print(e.message)
表象:能夠被for循環對象就能夠成爲是可迭代對象
class Foo: pass obj = Foo()
如何讓一個對象變成可迭代對象
__iter__
方法且返回一個迭代器(生成器)class Foo: def __iter__(self): return iter([1,2,3,4]) obj = Foo() class Foo: def __iter__(self): yield 1 yield 2 yield 3 obj = Foo()
只要能被for循環就是去看他內部的iter方法
import sys class Payment: # 這個類爲抽象類,爲了規範子類必須實現的父類的同名方法 def pay(self,money): # 須要傳參 raise NotImplementedError('請在子類中重寫pay方法') # 主動拋出異常 class Wechat(Payment): def __init__(self,name): self.name = name def pay(self,money): print('%s經過微信支付%s錢成功' %(self.name,money)) class Apple(Payment): def __init__(self,name): self.name = name def pay(self,money): # 經過繼承的關係來判斷方法名是否同樣,若是與歸一化設計的方法不一樣則會拋出異常 print(print('%s經過蘋果支付%s錢成功' % (self.name, money))) # 歸一化設計 def pay(name,price,kind): class_name = getattr(sys.moudles[__name__],'kind') # 經過反射獲得類的名字 obj = class_name(name) obj.pay(price) pay('alex',200,'Wechat') pay('alex',200,'Apple') ########## 另外一種方式:約束力強,依賴abc模塊 from abc import ABCMeta,abstractmethod class Payment(metaclass=ABCMeta): @abstractmethod def pay(self,money): pass '''只要你見到了項目中有這種類,你要知道你的子類中必須實現和pay同名的方法'''
概念 : 根據字符串的形式去某個對象中操做他的成員
getattr(對象,'字符串') 根據字符串的形式去某個對象中獲取對象的成員
獲取類中的屬性
class Foo(object): def __init__(self,name): self.name = name def func(self): print(123) obj = Foo('alex') # 獲取變量 v1 = getattr(obj,'name') print(v1) # alex getattr(obj,'func')() # 123
獲取當前py文件中的屬性
import sys def func(): print(123) name = 'alex' getattr(sys.modules[__name__],'func') # 123 print(getattr(sys.modules[__name__]),'name') # alex
引用模塊中的任意的變量
# a.py 中的屬性有: def func(): print('in func') name = 'alex' class User: pass obj = User() # 運行腳本的文件 import a getattr(a,'func')() # in func getattr(a,'obj') # 獲得地址 print(getattr(a,'name')) # alex
hasattr(對象,'字符串') 根據字符串的形式去某個對象中判斷是否有該成員
class A: job = 'IT' def __init__(self): self.name = 'alex' self.age = 83 def func(self): print('in func') a = A() print(hasattr(a,'sex')) # False print(hasattr(a,'func')) # True if hasattr(a,'func'): if callable(getattr(a,'func')): # 判斷這個函數是否可被調用 getattr(a,'func')() # in func
setattr(對象,"變量","值") 根據字符串的形式去某個對象中設置成員
class Foo: pass obj = Foo() obj.k1 = 999 setattr(obj,'k1',123) # obj.k1 = 123 print(obj.k1) # 123
delattr(對象,"變量") 根據字符串的形式去某個對象中刪除成員
class Foo: pass obj = Foo() obj.k1 = 999 delattr(obj,'k1') print(obj.k1)
經常使用操做
class User: lis = [('登入','login'), ('註冊','register'), ('刪除文件','remove'), ('複製文件','copy')] def login(self): print('in login') def register(self): print('in register') def remove(self): print('in remove') def copy(self): print('in copy') obj = User() for index,item in enumerate(obj.lis,1): print(index,item[0]) while True: num = input('請選擇要操做的序號:') if num.isdecimal() and 0 < int(num) <= len(obj.lis): if hasattr(obj,obj.lis[int(num)-1][1]): getattr(obj,obj.lis[int(num)-1][1])() else: print('輸入有誤')
# from utils import redis import importlib middleware_classes = [ 'utils.redis.Redis', # 'utils.mysql.MySQL', 'utils.mongo.Mongo' ] for path in middleware_classes: module_path,class_name = path.rsplit('.',maxsplit=1) module_object = importlib.import_module(module_path)# from utils import redis cls = getattr(module_object,class_name) obj = cls() obj.connect() # # 用字符串的形式導入模塊。 # redis = importlib.import_module('utils.redis') # # # 用字符串的形式去對象(模塊)找到他的成員。 # getattr(redis,'func')()
幾種表達形式
mes = '我是%s,年齡%s' %('Alex',99,) mes = '我是%(n1)s,年齡%(n2)s' %('n1':'Alex','n2':99) # v1 = "我是{0},年齡{1}".format('alex',19) v1 = "我是{0},年齡{1}".format(*('alex',19,)) print(v1) # v2 = "我是{name},年齡{age}".format(name='alex',age=18) v2 = "我是{name},年齡{age}".format(**{'name':'alex','age':18}) print(v2)
from collections import orderedDict #導入模塊將其轉換爲有序字典 info = OrderDict() info['k1'] = 123 info['k2'] = 456 print(info.keys()) print(info.values()) print(info.items())
class Foo: def __init__(self): self.l = [] def put(self,num): self.l.append(num) return self.l class Queue(Foo): # 隊列: 先進先出 def get(self): return self.l.pop(0) class Stack(Foo): # 棧: 後進先出 def get(self): return self.l.pop()
不管實例化多少次,永遠用的都是第一次實例化出對象
單例模式標準
#方法一 class Singleton: def __new__(cls,*args,**kwargs): if not hasattr(cls,'__instance'): cls.__instance = object.__new__(cls) return cls.__instance one = Singleton() two = Singleton() # 二者的內存地址徹底同樣 #方法二 class Baby: __instance = None def __new__(cls, *args, **kwargs): if cls.__instance is None: cls.__instance = super().__new__(cls) return cls.__instance def __init__(self,cloth,pants): self.cloth = cloth self.pants = pants b1 = Baby('紅毛衣','綠皮褲') print(b1.cloth) b2 = Baby('白襯衫','黑豹紋') print(b1.cloth) print(b2.cloth)
日誌處理本質; Logger / FileHandler / Formatter
日誌的做用:
輸出內容是有等級的: 默認處理warning級別及其以上的全部信息
logging.debug('debug message') # 調試 logging.info('info message') # 信息 logging.warning('warning message') # 警告 logging.error('error message') # 錯誤 logging.critical('critical message') # 批判性的 ''' 不管但願日誌打印那些內容,都是本身寫的,沒有自動生成日誌這種事 '''
將日誌輸出到屏幕
logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s[line :%(lineno)d]-%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S ', ) logging.warning('warning message test2') logging.error('error message test2') logging.critical('critical message test2')
輸出到文件,而且設置信息的等級,寫入文件會出現亂碼問題
logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s[line :%(lineno)d]-%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', filename='tmp.log', # 將日誌文件寫入到名爲tmp.log的文件中,以append的方式追加進去 level= logging.DEBUG # 設置最低處理等級爲DEBUG,等級必須大寫 ) logging.debug('debug 信息錯誤 test2') logging.info('warning 信息錯誤 test2') logging.warning('warning message test2') logging.error('error message test2') logging.critical('critical message test2')
同時向文件和屏幕上輸出,並解決亂碼問題 (經常使用這種方式處理日誌)
fh = logging.FileHandler('tmp.log',encoding='utf-8') # 向文件輸出並處理亂碼問題 # fh2 = logging.FileHandler('tmp2.log',encoding='utf-8') # 也可同時輸出到兩個文件 sh = logging.StreamHandler() # 輸出到屏幕 logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s[line :%(lineno)d]-%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', level= logging.DEBUG, # 設置最低處理等級爲DEBUG,等級必須大寫 # handlers=[fh,sh,fh2] handlers=[fh,sh] # 將須要輸出到的內容添加到handlers ) logging.debug('debug 信息錯誤 test2') logging.info('warning 信息錯誤 test2') logging.warning('warning message test2') logging.error('error message test2') logging.critical('critical message test2')
作日誌的切分
import time from logging import handlers sh = logging.StreamHandler() rh = handlers.RotatingFileHandler('myapp.log', maxBytes=1024,backupCount=5) # 按照大小作切割 fh = handlers.TimedRotatingFileHandler(filename='x2.log', when='s', interval=5, encoding='utf-8') logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s[line :%(lineno)d]-%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', level= logging.DEBUG, handlers=[fh,rh,sh] ) for i in range(1,10): time.sleep(1) logging.error('KeyboardInterrupt error %s'%str(i))