Python 3 筆記

来源:http://www.cnblogs.com/wcwnina/archive/2017/07/18/7203421.html
-Advertisement-
Play Games

############################################################################################ 內 容: Python 3 # 作 者: 娜愛# 更新日期: 2017.07.18 # 在cmd中執行py文件(路 ...


#########################################################################################
# 內 容: Python 3
# 作 者: wangchunwang
# 更新日期: 2017.07.14
# 在cmd中執行py文件(路徑可加雙引號),如:python E:\PythonSrc\mypy_package\eg.py
#########################################################################################

1、輸入函數:input(*args, **kwargs),輸入結果是字元串類型。輸出(列印)函數:print(*args, sep=' ', end='\n', file=None)。

2、Python數據類型都是“類(class)”類型。
dir(__builtins__):輸出所有Python內置變數和函數,首字母大寫的是異常名。
dir(__name__):輸出Python對象的屬性和方法。

3、Python提供了ord()函數獲取字元的Unicode數值,chr()函數把Unicode數值轉換為對應的字元。

數據類型:
(1)整型:int、bool
賦值方式:① x=99 ② x=int(99),如果是浮點數,則取整。
轉換函數:int(),bin(),oct(),hex()等。
進位表示法:二進位0b,八進位0o,十六進位0x。進行二進位計算時加首碼“0b”,其他類似。

(2)浮點型:float(雙精度)、complex(複數)、Decimal(定點數)
Decimal入參是整數或字元串,因為float精度不夠。

(3)字元串型:str (Unicode字元構成)
使用三引號並回車,可以格式化換行輸出。
使用“\”連接,可以換行書寫代碼。如:
s='abcd'\
'efgh'
s.strip(c) :去除空格或指定的字元c;
s.zfill(w) :寬度小於w,用0前補;
s.join(q) :用“s”將序列“q”中的元素串起來;
“ * ”能複製字元串、列表、元組等,如s='#'*9,即9個#;
s.rpartition('符號'):搜索出指定符號的最右邊的元素;
s.find(t) :返回t的最左位置,未找到,返回-1;
s.index(t):返回t的最左位置,未找到,返回ValueError異常;
s.ljust(w,c):左對齊,寬度w,填充符c;rjust右對齊。

s.format():格式化字元串,用{}配合使用。如'...{0}...{1}...{2}'.format('A','B','C') 或 '...{name}...{0}...'.format(20,name='She');
format參數說明:位置參數必須在關鍵字參數之前,可以傳字典參數。
format()可以格式規約,用冒號“:”引導規約:
'{0:20}'.format(s) #寬度20,預設左對齊
'{0:<20}'.format(s) #寬度20,左對齊
'{0:>20}'.format(s) #寬度20,右對齊
'{0:^20}'.format(s) #寬度20,中間對齊
'{0:*>20}'.format(s) #寬度20,右對齊,用*填充
'{0:.4}'.format(s) #最大寬度4,減除多餘部分
'{0:+20}'.format(num) #對於數值num,寬度20,帶符號輸出
'{0:#x}'.format(num) #返回十六進位形式,#b二進位,#o八進位
'{0:,}'.format(num) #三個數字逗號分組,如銀行數
'{0:.2f}'.format(num) #帶2位小數的浮點數
'{0:e}'.format(num) #科學計數

(4)位元組(二進位)類型:
bytes(固定的)、bytearray(可變的,可插入可刪除某個字元)。
如,bin=b'python' 或 'python'.encode()
binarr=bytearray(bin), binarr.pop(1), binarr.insert(1,ord('a'))

4、運算符“/”結果是浮點數,“//”結果是整數,“**”表冪運算。
is: 基於記憶體的身份比較。如,x=('python'),y=('python'),x is y 返回False。
比較操作符: 基於對象值比較。如,x=('python'),y=('python'),x == y 返回True。Python可以進行結鏈比較,1 <= a <= 3。
id: 獲取記憶體地址。
in: 理解為屬於,判斷成員關係,val in x。
and 、or: 與、或。短運算邏輯,返回布爾值,或決定結果的操作數。
not: 非。總是返回布爾值。
del obj: 只是刪除引用對象(當無任何引用對象時,數據才被回收)。
[]: 切片操作符或項目操作符。

6、ASCII編碼:只有127個字元;
Unicode編碼:常用的是用2個位元組表示一個字元(如果要用到非常偏僻的字元,就需要4個位元組);
UTF-8編碼:常用的英文字母被編碼成1個位元組,漢字通常是3個位元組,只有很生僻的字元才會被編碼成4-6個位元組。

7、方法encode('編碼格式'):如,'中文'.encode('utf-8')。

8、方法decode('解碼格式'):如,b'\xe6\xb1\xaa'.decode('utf-8')。Python對bytes類型的數據用帶“b”首碼的單引號或雙引號表示。

9、r'\字元':使轉義無效。

10、#!/usr/bin/env python3
告訴Linux/OS X系統,這是一個Python可執行程式,Windows系統會忽略這個註釋;
# -*- coding: utf-8 -*-
告訴Python解釋器,按照UTF-8編碼讀取源代碼,否則,你在源代碼中寫的中文輸出可能會有亂碼。

Python文件名不能和關鍵字、模塊名相同,否則很可能會報找不到屬性的錯誤。

11、格式化(變數前加格式):
%d 整數
%f 浮點數
%s 字元串
%x 十六進位整數
如,print('成績增長率:%.2f' %(num)) #保留兩位小數

12、列表(list),定義用“[]”:有序、重覆,如果要取最後一個元素,除了計算索引位置外,還可以用-1做索引,直接獲取最後一個元素,以此類推,可以獲取倒數第2個、倒數第3個。
若L=[...]
print(L) #整個列表
print(*L) #用“*”拆出列表所有元素

組合類型函數,list(),tuple(),dict(),set(),frozenset()只能傳入一個參數。

13、方法append():追加,obj.append('A');
方法insert():指定位置插入,obj.insert(1, 'Jack');
方法pop(i) :指定位置刪除,obj.pop(i),pop(0)指刪除末尾,其中i是索引位置或字典的鍵;
方法remove():刪除已知元素;
要把某個元素替換成別的元素,可以直接賦值給對應的索引位置,如,obj.[1] = 'Sarah';

14、元組(tuple),定義用“()”:有序、重覆,tuple和list非常類似,但是tuple一旦初始化就不能修改,只讀,更安全。
如果可能,能用tuple代替list就儘量用tuple。
最好以“,”結尾,當tuple只有一個元素時,必須以“,”結尾。

15、for <元素> in <範圍>:,迴圈就是把每個元素代入變數x,然後執行縮進塊的語句。
for _ in range(n):,使用下劃線“_”,迴圈n次執行迴圈體。此時“_”作為臨時性的名稱使用,忽略迴圈計數中的實際值。

16、range(x1,x2,步長)函數,可以生成一個整數序列,長度為(x2-x1)。

17、不要濫用break和continue語句。break和continue會造成代碼執行邏輯分叉過多,容易出錯。
大多數迴圈並不需要用到break和continue語句。

18、字典(dict),定義用“{'k':'v'}”:無序、不重覆,在其他語言中也稱為map,使用可哈希演算法的鍵-值("key":"value")存儲,具有極快的查找速度。字典無序。
通過in判斷key是否存在,如果key不存在,可以返回false:'Thomas' in d;
d.get(k,v):返回k對應的值,如果k不存在,則返回None;
d.setdefault(k,v):設置k-v鍵值對,如果k存在,則返回v值;
清除所有:clear(),淺拷貝:copy(),移除:pop()。

19、zip(iter1,...):依次取出每個iter元素組合成tuple,可轉成list輸出。如,list(zip([1,2],['a','b'])) -->[(1,'a'),(2,'b')]。

20、dict內部存放的順序和key放入的順序是沒有關係的。
和list比較,dict有以下幾個特點:
1).查找和插入的速度極快,不會隨著key的增加而變慢;
2).需要占用大量的記憶體,記憶體浪費多。

而list相反:
1).查找和插入的時間隨著元素的增加而增加;
2).占用空間小,浪費記憶體很少。

21、集合(set),定義用“set({'v'})”或“{'v'}”:無序、不重覆,集合可變,但集合元素是可哈希運算的(不可變)。
添加:obj.add('值'),移除:obj.remove('值'),清除:obj.clear(),淺拷貝:obj.copy()。
交集:set1 & set2,並集:set1 | set2,交集之外:set1 ^ set2

固定集合(frozenset),不可變的集合。

22、“不可變對象”:str、tuple、dict、set。
“可變對象”:list。
對於不變對象來說,調用對象自身的任意方法,也不會改變該對象自身的內容。
相反,這些方法會創建新的對象並返回,這樣,就保證了不可變對象本身永遠是不可變的。

23、如果想定義一個什麼事也不做的空函數,可以用pass語句,如:
def nop():
pass
實際上pass可以用來作為占位符,比如現在還沒想好怎麼寫函數的代碼,就可以先放一個pass,讓代碼能運行起來以致不報錯。

24、數據類型檢查可以用內置函數isinstance()實現:isinstance(x,(int,float))。

25、raise TypeError('bad operand type'):拋出異常信息。

26、包:必須包含一個“__init__.py”文件。
import importname[.modulename as newname] ,使用“as”能避免同名同API的包衝突。
from importname import * ,導入非私有的一切對象,使用“*”會調用該包的“__init__.py”模塊中“__all__”語句。
相對導入:from ..dir import modulename。
將包或模塊放入“C:\Python\Lib\site-packages”中,對所有程式都可用。

27、return(或return None),跳出函數。
函數可以同時返回多個值,但其實就是一個tuple。

28、位置參數:傳參時,可以直接寫值,也可以是“參數名=值”。

預設參數:可看作是單一的字典參數,必須放位置參數之後!!
定義預設參數要牢記一點:預設參數必須指向不變對象!
備註:任何參數入參時都可以用“參數名=值”的方式指定入參。

29、可變參數(類似於重載):“*nums” 表示把nums這個“list”或“tuple”的多個元素作為可變參數傳進去,定義函數時往往需配用for..in..,如:
不使用可變參數則可用元組或列表:
def calc(arg),用法:calc((arg1,arg2,arg3,));
使用可變參數則可直接輸入多個參數:
def calc(*arg),用法:calc(arg1,arg2,arg3)。
註意:可變參數之後的參數進行入參時,必須寫“參數名=值”的形式表達。預設參數在可變參數之後!

30、字典參數(關鍵字參數):“ **kw ”表示把kw這個dict的所有key-value用關鍵字形式傳入到函數的參數中,如:
def func(**kw):
print('keys:{0},vals:{1}'.format(kw.keys(),kw.values()))

用法(調用時必須帶上**):
extra = {'city': 'Beijing', 'job': 'Engineer',...}
func(**extra) #等價於,func(**{'city': 'Beijing', 'job': 'Engineer',...})
或者一個一個地傳入鍵值:
func(mycity1='Beijing',mycity2='shanghai',...)。

31、命名字典參數:限制關鍵字參數的名字,需要一個特殊分隔符“*”,“*”後面的參數被視為命名關鍵字參數。
例如,只接收city和job作為關鍵字的參數,如:
def person(name, age, *, city, job)
函數調用時不要帶上*。

32、大多數編程語言沒有針對尾遞歸做優化,Python解釋器也沒有做優化,所以任何遞歸函數都存在棧溢出的問題。

控制結構。
1、if cond:
...
elif cond:
...
else: #else可選
...
if語句的簡單形式:exp if condition else val

2、while cond:
...
else: #else可選,條件不滿足時
...

3、for elem in iter:
...
else: #else可選,迴圈結束後
...

33、切片“[]”:mylist['開始索引':'結束索引':'±步長'],“+”正向切片,“-”逆向切片。
註意:不包含結束索引的位置,如果要包含“結束索引”的值,請將“結束索引”加1。
tuple也可以用切片操作,只是操作的結果仍是tuple;
字元串也可以看成是一種list,也可以用切片操作,只是操作結果仍是字元串。
字元串翻轉:str(mystr)[::-1]

34、預設情況下,“dict”迭代的是key。如果要迭代value,可以用for value in d.values(),如果要同時迭代key和value,可以用for k, v in d.items()。

35、判斷一個對象是可迭代:
from collections import Iterable
print(isinstance('12345',Iterable))

36、函數enumerate():可以把一個list的每個元素變成“ 序號+元素 ”對(tuple)。

37、列表生成式。
[i_exp for i in range(1, 11) if i % 2 == 0],使用[]轉成列表,生成的元素放前面(表達式),後面跟for迴圈。可以for嵌套、if條件。
將迴圈結果進行了表達式運算並保存結果到列表中,直接列印出print(mylist)。

集合生成式。
{i_exp for i in range(1, 11) if i % 2 == 0},使用{}轉成集合。

字典生成式。
{k_exp:v_exp for k,v in iterable if condition},使用{}轉成字典。

38、生成器(generator)。創建一個生成器後,基本上不會調用next(),而是通過“ for ”迴圈來迭代它,並且不需關心StopIteration的錯誤。
第一種(類似於迭代),只要把一個列表生成式的[]改成()。不必一次性創建整個list,而是迭代生成,從而節省大量的空間。如:
gen=(i*i for i in range(1, 11) if i % 2 == 0)

第二種(類似於中斷),利用關鍵字“yield”則變成了生成器,yield只用於函數中,遇到yield語句中斷返回,再次執行時從上次返回的yield語句處繼續執行。例:
#斐波拉契數列#
def fib(max):
n=0
a,b=(0,1) #利用tuple分別賦值
while n<max:
# print(b)
yield b
a,b=(b,a+b)
n+=1

for v in fib(6): #一般使用for迴圈輸出
print(v)

#楊輝三角#
def yanghui(lines):
L=[]
n=0
while n<=lines:
yield L
L = [1] + [L[x-1] + L[x] for x in range(1,len(L))] + [1]
n+=1
for v in yanghui(10):
print(v)

39、可迭代(Iterable):凡是可作用於for迴圈的對象都是Iterable類型;
迭代器(Iterator):凡是可作用於“next()”函數的對象都是Iterator類型,它們表示一個惰性計算的序列;
可迭代的類型有:list、tuple、dict、set、str等。
可以通過iter()函數獲得一個迭代器(Iterator)對象。

40、高階函數:把函數作為參數傳入,這樣的函數稱為高階函數,函數式編程就是指這種高度抽象的編程範式。

41、函數map(函數f,Iter):即映射,函數f接收兩個參數,一個是函數名,一個是可迭代的定義域集合(Iterable)。結果是個迭代器(Iterator)。

42、函數reduce(函數f,Iter):函數f(arg1,arg2),該函數f返回的結果又作為arg1,這樣的函數f作用在Iter元素上進行累積計算。如,
from functools import reduce
def f(arg1,arg2):
return arg1*arg2
def prod(ls):
res=reduce(f,ls)
return res
print(prod([10,2,4,5]))

43、函數filter(函數f,Iter):過濾。函數f作用在Iter元素上,若函數f返回True則留下該Iter的元素,若返回False則濾除掉該Iter的元素。

44、函數sorted(Iter,<key=函數名>,<reverse=False>):排序。可以通過函數完成自定義排序,該函數作用在Iter元素上。如:
sorted({'d':4,'b':2,'a':1,'c':3}, key=lambda e:e[0], reverse=False) #e[0]自動迭代,按鍵排序

45、一個函數可以返回一個計算結果,也可以返回一個函數。
返回一個函數時,牢記該函數並未執行,返回函數中不要引用任何可能會變化的變數。

46、當我們在傳入函數時,有些時候,不需要顯式地定義函數,直接傳入匿名函數(λ)更方便。
lambda 參數: 表達式。如,lam = lambda x: x**2,則可顯式調用lam(3)=9。
sorted.L(key=lambda ele: abs(ele)),隱式調用,會自動將列表L每個元素傳入ele。

47、偏函數:當函數的參數個數太多,需要簡化時,使用“functools.partial”可以創建一個新的函數,這個新函數可以固定住原函數的部分參數,從而在調用時更簡單。如:
int2 = functools.partial(int, base=2)

48、模塊:一個.py文件就稱之為一個模塊。最大的好處是大大提高了代碼的可維護性。
導入模塊:“ from 包名 import 模塊名 ”。

49、if __name__=='__main__':
test()
這句話表示,僅當直接執行本模塊時,執行if代碼塊。當其他模塊調用此模塊時,則忽略該代碼塊。

50、類是抽象的模板,實例是根據類創建出來的一個個具體的“對象”,每個對象都擁有相同的方法,但各自的數據可能不同。
class Student(object):
def __init__(self): #重寫object中__init__()方法初始化。可用super().__init__()調用父類的__init__()初始化。
pass
pass
class後面緊接著是類名,即Student,類名通常是大寫開頭的單詞,緊接著是繼承類(預設為object,在builtins.py模塊中第720行~820行),表示該類是從哪個類繼承下來的。

“self”一般用在類方法中,表示只有實例對象能訪問,而類對象不能訪問。作用:調用自身(實例)的屬性或方法。
類方法外部的屬性,類對象可以訪問,而實例對象不能訪問。

實例對象:stu=Student([args]),自動進行了兩個步驟,首先調用__new__()方法創建實例對象,然後調用__init__()初始化。

Python要麼是public要麼就是private,一般要避免下劃線的使用。
以單下劃線開頭(_foo):視為受保護的成員,視為不要在外部使用;
以雙下劃線開頭的(__foo):真正的私有成員,只能在類自己內部中使用;
以雙下劃線開頭和結尾的(__foo__):特殊方法專用的標識,如 __init__()構造函數。這類特殊方法可以重定義,但不是同名調用,而是使用操作符或調用去掉雙“__”的方法。

51、多態:一個類的實例可以是該類的類型,也可以是父類的類型,但不可以是其子類的類型。

52、對於靜態語言(例如Java)來說,如果需要傳入Animal類型,則傳入的對象必須是Animal類型或者它的子類,否則,將無法調用其中的方法。
對於Python這樣的動態語言(“鴨子語言”:如果某個對象調用某個方法,就不必管該對象屬於哪個類,只要存在需要調用的方法即可)來說,
則不一定需要傳入Animal類型,我們只需要保證傳入的對象有其方法就可以了。

53、方法type(數據參數):返回數據類型。

54、函數與方法區別:
方法(類的)調用方式: 對象.方法名()
函數調用方式: 函數名(對象)
方法的第一個參數是自調參數(self),函數沒有自調參數。

55、函數getattr(對象/類名,屬性名):獲取對象/類名屬性;
函數setattr(對象/類名,屬性名):設置對象/類名屬性;
函數hasattr(對象/類名,屬性名):判斷對象/類名屬性是否存在。

56、動態添加(綁定)屬性:
“對象名.新屬性名” = “值” , 此方式添加的屬性只對該實例對象有效;
“類名.新屬性名” = “值” , 此方式添加的屬性對所有實例對象有效;
“動態”缺點:無法做屬性檢查,而自定義的“getter()”和“setter()”可以做參數的檢查,如判斷等。

57、動態添加(綁定)方法:
“對象名.新方法名” = “已定義函數名” , 此方式添加的方法只對該實例對象有效;
“類名.新方法名” = “已定義函數名” , 此方式添加的方法對所有實例對象有效;

58、變數__slots__=('屬性1','屬性2',...):限制類屬性,對象只能訪問和添加的屬性。但對繼承的子類是不起作用的。

hasattr(object, name):
判斷一個對象裡面是否有name屬性或者name方法,返回BOOL值,有name特性返回True, 否則返回False。

getattr(object, name[,default]):
獲取對象object的屬性或者方法,如果存在列印出來,如果不存在,列印出預設值,預設值可選。

setattr(object, name, values):
給對象的屬性賦值,若屬性不存在,先創建再賦值。

59、@property 屬性裝飾器:把取值、賦值(getter()、setter())方法變成屬性,則可以通過“obj.__attr”取值,通過“obj.__attr=val”賦值(最好使用私有屬性)。
@property 屬性裝飾器廣泛應用在類的定義中,可以讓調用者寫出簡短的代碼,同時保證對參數進行必要的檢查,如判斷等,這樣,程式運行時就減少了出錯的可能性。
例:
class Money:
def __init__(self, dollars, cents):
self.__total_cents = dollars * 100 + cents

#直接使用@property,取值-->obj.cents,相當於obj.getter()
@property
def cents(self):
return self.__total_cents % 100;
#使用@方法名.setter,賦值-->obj.cents=val,相當於obj.setter()
@cents.setter
def cents(self, new_cents):
self.__total_cents = 100 * self.dollars + new_cents

#實例
m=Money(1,1)
m.cents #取值
m.cents=2 #賦值

@classmethod 類方法裝飾器(classname.classmethod)。

60、MixIn:在設計類的繼承關係時,通常,主線都是單一繼承下來的,如果需要“混入”額外的功能,通過多重繼承就可以實現,這種設計通常稱之為MixIn(混合)。

61、動態創建類:
myclass=type('MyClass',(object,),{'func':exfn})
說明:'MyClass':類名;
(object,):繼承類,用tuple;
{'func':exfn}:類方法,dict型,其中exfn是外部定義好的方法。

62、捕獲異常
try:
pass
except Exception as e: #儘量指定精確的異常類
pass
raise #可以在這裡拋出異常,讓上層調用者處理。程式不會往下執行。如果沒有拋出,程式會繼續往下執行。
else: #可選,try正常結束後
pass
finally: #可選,總是被執行
pass
當認為某些代碼可能會出錯時,就可以用try來運行這段代碼,如果執行出錯,則後續代碼不會繼續執行,而是直接跳轉至錯誤處理代碼,
即except語句塊,執行完except後,如果有finally語句塊(非必需),則執行finally語句塊,至此,執行完畢。
所有的錯誤類型都繼承自BaseException,所以在使用except時需要註意的是,它不但捕獲該類型的錯誤,還把其子類也“一網打盡”。

錯誤和異常:
錯誤,機器出現的錯誤不需要處理。
異常,程式運行而能自動識別的異常,一般要捕獲處理(立即處理或上拋給調用者)。系統異常與邏輯異常。

63、如果要列印錯誤追蹤,導入logging,如:
import logging
...
except Exception as e:
logging.exception(e) #不需要print(),直接輸出錯誤日誌追蹤。

64、拋出異常
a、raise Exception('str')
b、raise # raise語句如果不帶參數,就會把當前錯誤原樣拋出給調用者。

65、調試。
(1)使用assert語句。面向開發者設計,用於程式的調試。
凡是用print()來輔助查看的地方,都可以用斷言(assert)來替代。
assert 表達式,'輸出提示' ,其中,若“表達式”為假,程式終止,並給出“輸出提示”;為真,程式繼續執行,無輸出提示。
(2)使用logging語句,服務端寫入日誌,還可以通過http get/post,socket,email寫入日誌。
import logging
logging.basicConfig(level=logging.INFO) #有debug,info,warning,error等幾個級別
...
logging.info()

66、閉包:如果外部函數里有內部函數,內部函數對外部作用域(但不是在全局作用域)的變數進行引用,那麼內部函數就被認為是閉包(closure)。
裝飾器就是一種閉包!
調用外部函數傳遞的參數就是自由變數。
簡單說,閉包就是根據不同的配置信息得到不同的結果。
用途1:當閉包執行完後,仍然能夠保持住當前的運行環境。(類似靜態變數)
用途2:閉包可以根據外部作用域的局部變數來得到不同的結果。(這有點像一種類似配置功能的作用,我們可以修改外部的變數,閉包根據這個變數展現出不同的功能。)
如:
def exfunc(x):
def clofunc(y):
return x + y
return clofunc
調用:f=exfunc(6) # x=6,返回了內部函數clofunc賦給f,即此時調用內部函數。
print(f(8)) # y=8

67、裝飾器(decorator):使用@調用裝飾器。在不更改原函數的情況下,該函數被調用前,擴展該函數功能。
故裝飾器以函數入參,並返回內部函數。例:
def deco(func): #裝飾器函數
def wrapper(*args,**kw): # “*args,**kw”,表示可接收任何參數
print('調用了%s()' % func.__name__)
return func(*args,**kw) #返回入參函數
return wrapper #返回內部函數,閉包。

@deco
def now():
print('2017-5-4')

68、IO:涉及到數據交換的地方,通常是磁碟、網路等,就需要IO介面。
從磁碟【讀】文件到記憶體,就只有【Input】操作,反過來,把數據【寫】到磁碟文件里,就只是一個【Output】操作。
現代操作系統不允許普通的程式直接操作磁碟,所以,讀寫文件就是請求操作系統打開一個文件對象(通常稱為文件描述符)。

69、讀文件。
如果文件很小,read()一次性讀取最方便;如果不能確定文件大小,反覆調用read(size)比較保險;如果是配置文件,調用readlines()最方便。
無論讀寫,都先打開(open)文件的路徑,即入口。
例:try:
f=open('D:\Personal\Desktop\PyNote.py','r') #先打開文件
print(f.read()) #一次性全部讀取
except IOError as e:
print('讀入文件出錯',e,sep='||')
finally:
f.close() #無論如何需要關閉流

*推薦使用:另一種簡潔讀文件方法(不必調用close()方法),使用with語句操作文件IO是個好習慣:
with open('D:\Personal\Desktop\PyNote.py','r') as file:
print(file.read())
70、寫文件。
當我們寫文件時,操作系統往往不會立刻把數據寫入磁碟,而是放到記憶體緩存起來,空閑的時候再慢慢寫入。
只有調用close()方法時,操作系統才保證把沒有寫入的數據全部寫入磁碟。
忘記調用close()的後果是數據可能只寫了一部分到磁碟,剩下的丟失了。所以,還是用with語句來得保險,例:
*推薦使用:
with open('D:\Personal\Desktop\PyNote1.txt','w') as file:
file.write('寫文件!') #返回字元長度

71、字元流(StringIO)。StringIO和BytesIO是在記憶體中操作str和bytes的方法,使得和讀寫文件具有一致的介面。流必須先讀出來再寫入文件中。
from io import StringIO,並先創建一個StringIO實例。以下例1、2均可用getvalue()方法獲取流。
例1:使用write()寫入流中。
f=StringIO() #創建一個StringIO實例
f.write('字元流IO')
print(f.getvalue()) #用getvalue()方法獲取流。
#write()結束後指針在末尾,使用方法tell()能知道指針位置,所以read()方法讀取不到。
#除非用方法seek(i)將指針定位開始位置,則可以用read()方法讀取。
例2:初始化流,用read()方法讀取流。
f = StringIO('Hello!\nHi!\nGoodbye!') #初始化流,指針在開頭
while True:
s = f.readline() #可用read()方法讀取流
if s == '':
break
print(s.strip()) #strip()去除首尾空格
72、位元組流(BytesIO)。類似於字元流。以下例1、2均可用getvalue()方法獲取流。
例1:使用write()寫入流中。
from io import BytesIO
b=BytesIO() #創建一個BytesIO實例
b.write('位元組流'.encode())
print(b.getvalue()) #用getvalue()方法獲取流。
#write()結束後指針在末尾,使用方法tell()能知道指針位置,所以read()方法讀取不到。
#除非用方法seek(i)將指針定位開始位置,則可以用read()方法讀取。
例2:初始化流,用read()方法讀取流。
b=BytesIO('位元組流'.encode()) #初始化流,指針在開頭
print(b.read()) #可用read()方法讀取流

73、操作目錄或文件:導入os包,import os (當前路徑 sys.argv[0])
(1)創建目錄:os.mkdir('路徑')
(2)刪除目錄:os.rmdir('路徑')
(3)目錄列表:os.listdir('路徑')
(4)產生一個當前絕對路徑的字元串:os.path.abspath('name'),其中的name也可以是指定的完整路徑。當name是“.”表示當前完整目錄。
(5)拼接路徑(處理不同操作系統路徑規則):os.path.join('D:\Personal','mydir')
(6)拆出一個路徑的末尾:os.path.split('D:\Personal\Desktop\mydir.py'),-->結果是('D:\\Personal\\Desktop', 'mydir.py')
(7)拆出擴展名:os.path.splitext('D:\Personal\Desktop\mydir.py'),-->結果是('D:\\Personal\\Desktop\\mydir', '.py')
返迴文件名(含擴展名):os.path.basename('D:\Personal\Desktop\mydir.py'),-->結果是'mydir.py'
(8)文件最後修改時間戳:os.path.getmtime('路徑')
(9)目錄樹:os.walk('路徑')

解壓與壓縮(import gzip)。
解壓(讀):
f = gzip.open('file.txt.gz', 'rb') #打開解壓路徑
file_content = f.read() #直接解壓
f.close()

壓縮(寫):
air=open('Air.xml')
fh=StringIO(air.read()) #字元流緩存
airzip=gzip.open('AirZip.xml.gz','wb') #打開壓縮路徑
airzip.write(fh.getvalue().encode()) #直接壓縮
air.close()
airzip.close()

74、(1)序列化(pickling):把對象轉成位元組(持久化二進位文件)。經常遇到在Python程式運行中得到了一些字元串、列表、字典等數據,
想要長久的保存下來,方便以後使用,而不是簡單的放入記憶體中關機斷電就丟失數據。它可以將對象轉換為一種可以傳輸或存儲的格式。如:
import pickle
1)序列化:
pickle.dumps(obj) #註意是生成位元組byte,dumps()
2)dump(),序列“寫入”文件中:
file=open('D:\Personal\Desktop\mypy.txt','wb') #'wb',以位元組寫入
pickle.dump(obj,file,protocol=0) #序列並寫入,dump(),不帶字母“s”的方法與文件相關。protocol=0 為ASCII,1是舊式二進位,2是新式二進位協議
file.close()
3)load(),反序列“讀取”:
file=open('D:\Personal\Desktop\myp1y.txt','rb') #'rb',以位元組讀取
pickle.load(file) #反序列,load()
file.close()
序列化的缺點:1.只能用於Python,並且可能不同版本的Python彼此都不相容。2.不安全。

(2)struct結構體:類似C語言的結構體,包含不同類型的數據。將特定的結構體類型打包成位元組型數據(二進位流)然後再網路傳輸,
而接收端也應該可以通過某種機制進行解包還原出原始的結構體數據。網路通信當中,大多傳遞的數據是以二進位流存在的。
import struct #打包方法:pack(fmt,values)
bin_data = struct.pack('>i3sf', 1, b'abc', 2.7) #按格式打包成位元組,“>”位元組順序,“i”32位整型,“3s”長度為3的字元串,“f”浮點型。
print(bin_data) #字元串需要轉成位元組,且指定長度。
struct.unpack('>i3sf',bin_data) #解包還原,返回元組
或:
strc=struct.Struct(fmt) #初始化打包/解包格式fmt
strc.pack(data)
strc.unpack(bin_data)

75、JSON序列轉化(一定是雙引號格式)。導入json模塊。JSON不僅是標準格式,並且比XML更快,而且可以直接在Web頁面中讀取,非常方便。
import json
json.dumps(dic_obj) #dic_obj是字典類型
JSON反序列:
json_str='{"name":"wcw","addr":"bj"}' #註意用單引號包起來
inv_json=json.loads(json_str)
print(inv_json) #結果是字典
類對象的JSON序列:
stu=Student('wcw',20,100) #實例
json.dumps(stu.__dict__) #用內置屬性__dict__
或者 json.dumps(stu,default=lambda obj:obj.__dict__)

76、進程。任何進程預設就會啟動一個線程,我們把該線程稱為主線程。
對於操作系統來說,一個任務就是一個進程(Process)。有些進程還不止同時乾一件事,把進程內的這些“子任務”稱為線程(Thread)。
線程是最小的執行單元,而進程由至少一個線程組成。
獲取操作系統的進程ID:import os 然後 os.getpid()。
(1)創建一個進程。需要導入模塊:from multiprocessing import Process,實例一個進程類。
if __name__=='__main__':
p=Process(target='子進程名',arg=('子進程的參數',)) #實例一個子進程,target傳入函數,arg是元組。
p.start() #運行進程
p.join() #等待子進程結束後再繼續往下運行

(2)如果要啟動大量的子進程,可以用“進程池”的方式批量創建子進程。需要導入模塊:from multiprocessing import Pool。
if __name__=='__main__':
p=Pool(3) #實例子進程池,參數3表示可同時進行3個子進程
p.apply_async(func=task,args=(i,)) #運行進程池,func傳入函數,arg是元組
p.close() #調用join()之前必須先調用close()
p.join() #等待子進程結束後再繼續往下運行

77、進程通信:Python的multiprocessing模塊包裝了底層的機制,提供了Queue、Pipes等多種方式來交換數據。例:
def write(que): #寫的程式
print('調用寫進程%s' %os.getpid())
for val in ['AA','BB','CC','DD']:
print('把%s放入Queue中' %val)
que.put(val)
time.sleep(random.random())

def read(que): #讀的程式
print('調用讀進程%s' %os.getpid())
while True:
val=que.get()
if val==' ':
break
print('從Queue中讀出%s' %val)
time.sleep(random.random())

if __name__=='__main__':
que=Queue() #實例一個通信列隊,並傳給各個子進程
proc_write=Process(target=write,args=(que,)) #寫的子進程
proc_read=Process(target=read,args=(que,)) #讀的子進程
proc_write.start()
proc_read.start()
proc_write.join()
proc_read.terminate() #在這裡讀進程是死迴圈,方法terminate()強制終止。
print('the end')

78、線程。
Python的標準庫提供了兩個模塊:_thread和threading。_thread是低級模塊,threading是高級模塊,絕大多數情況下,只使用threading這個高級模塊。
import threading
print('當前線程:%s' %threading.current_thread())
thr=threading.Thread(target=函數名,name='自定義線程名',args=('函數參數',)) #實例一個線程
thr.start()
thr.join()

線程鎖:多線程和多進程最大的不同在於,多進程中,同一個變數,互不影響;而多線程中,所有變數都由所有線程共用,所以,
線程之間共用數據最大的危險在於多個線程同時改一個變數,把內容給改亂了。
Python解釋器由於設計時有全局鎖(GIL),導致了多線程無法利用多核。
例:
lock = threading.Lock() # 先要獲取鎖
lock.acquire()
try:
tread_func() #對線程調用的函數上鎖
finally:
lock.release() #改完了一定要釋放鎖,否則那些等待鎖的線程將永遠等待下去,成為死鎖

79、ThreadLocal應運而生,不用查找dict(這是定義全局的dict,key作為某個Thread,value作為屬性),ThreadLocal幫你自動做這件事。
ThreadLocal最常用的地方就是為每個線程綁定一個資料庫連接,HTTP請求,用戶身份信息等,
這樣一個線程的所有調用到的處理函數都可以非常方便地訪問這些資源。例:
import threading
local_school = threading.local() #實例一個ThreadLocal對象,用於封裝屬性,並能保證多線程使用該屬性而不互相干擾
#線程調用的方法
def thread_student_func(name, age, score):
local_school.name = name #封裝屬性
local_school.age = age
local_school.score = score
thread_student()

def thread_student():
name = local_school.name #讀取TreadLocal屬性
age = local_school.age
score = local_school.score
print('name:%s,age:%d,score:%0.1f' % (name, age, score), threading.current_thread().ident)

thr1 = threading.Thread(target=thread_student_func, args=('汪春旺', 25, 99.5))
thr2 = threading.Thread(target=thread_student_func, args=('娜娜', 20, 90))
thr1.start()
thr2.start()
thr1.join()
thr2.join()

80、進程 VS 線程。
要實現多任務,通常我們會設計Master-Worker模式,Master(主進程/線程)負責分配任務,Worker(子進程/線程)負責執行任務
進程優點:穩定性高,因為一個子進程崩潰了,不會影響主進程和其他子進程。
進程缺點:耗CPU和記憶體。

線程優點:效率高。
線程缺點:任何一個線程掛掉都可能直接造成整個進程崩潰,因為所有線程共用進程的記憶體。

任務分為計算密集型和IO密集型。
計算密集型(C語言)任務主要消耗CPU資源。IO密集型(Python語言)任務主要涉及到網路、磁碟IO。

在Thread和Process中,應當優選Process,因為Process更穩定,而且,Process可以分佈到多台機器上,而Thread最多只能分佈到同一臺機器的多個CPU上。

分散式進程:Python的multiprocessing模塊不但支持多進程,其中managers子模塊還支持把多進程分佈到多台機器上。

81、正則表達式,需導入re模塊。強烈建議使用Python的“r”首碼,就不用考慮轉義的問題。
字元:
\d 匹配一個數字
\w 匹配一個數字或字母
. 匹配任意字元
\字元 匹配某個指定字元,或者直接寫該字元
\s 匹配一個空格
數量:
* 任意個
+ 至少一個
? 0個或一個
{n} n個
{n,m} n~m個
指定字元範圍用[-]:
[0-9a-zA-Z\_]可以匹配一個數字、字母或者下劃線
| 或
^ 行的開頭,^\d表示必須以數字開頭,最好每次都帶上
$ 行的結束,\d$表示必須以數字結束,最好每次都帶上

用正則表達式切分字元串比用固定的字元更靈活,如:
re.split(r'\s+', 'a b c') #必須是re包的split()方法。以一個或多個空格切分。

正則表達式分組:用“()”表示的就是要提取的分組,方法group()獲取某一個分組,groups()獲取所有分組。
正則匹配預設是貪婪匹配,也就是匹配儘可能多的字元。加問號“?”可以去除貪婪匹配。如:re.match(r'^(\d+?)(0*)$', '102300').groups()

82、幾個常用的內置模塊。
(1)datetime日期時間模塊。
from datetime import datetime
datetime.now().hour #獲取當前日期時間
datetime(2017,5,20,13,14,0) #指定日期時間,返回datetime對象

時間戳(timestamp)一旦確定,其UTC(時區)時間就確定了。
如果要存儲datetime,最佳方法是將其轉換為時間戳(timestamp)再存儲,因為時間戳與時區完全無關。時間戳是一個浮點數。
datetime.timestamp('datetime對象') #日期時間-->時間戳,若是字元串需要把字元串轉成datetime對象
datetime.fromtimestamp('戳') #時間戳-->日期時間

datetime.strptime('2017-5-21','%Y-%m-%d') #字元串-->日期時間 (常用,註意參數的分隔符一致即可)
datetime.strftime(now,'%Y-%m-%d %H:%M:%S') #日期時間-->字元串

日期時間的加減,需要導入timedelta這個類。
now+timedelta(hours=1)

時區(UTC):from datetime import datetime,timedelta,timezone
utc_curr=datetime.utcnow().replace(tzinfo=timezone.utc) #utcnow() 返回當前時區,replace() 替換成預設時區UTC
bj_utc=datetime.astimezone(utc_curr,timezone(timedelta(hours=8))) #astimezone() 轉換成指定時區

(2)collections集合模塊。
1、namedtuple(type_name,field_name):命名的元組。將“type_name”視為表名,“field_name”視為欄位名。如:
point = namedtuple('poi','x , y')
p = point('abc','100') #賦值
print(p.x, p.y) #取值

2、deque(iterable):雙隊列。為了高效實現插入和刪除操作的雙向列表list,適合用於隊列和棧。因為list是線性存儲,數據量大的時候,插入和刪除效率很低。
deque除了實現list的append()和pop()外,還支持appendleft()和popleft()。

3、defaultdict(default_func):使用dict時,如果引用的Key不存在,就會拋出KeyError。如果希望key不存在時,返回一個預設值,就可以用defaultdict。如:
def_dic = defaultdict(lambda:'none')
def_dic['k1'] = 'a1'

4、OrderedDict類:使用dict時,Key是無序的,如果要保持Key的順序,可以用OrderedDict,如:
orddic=OrderedDict({'1':'a','2':'b','3':'c'})

5、Counter類:是一個簡單的計數器,例如,統計字元出現的個數。
c=Counter()
for t in 'wangchunwang':
c[t]=c[t]+1
print(c.most_common())

6、heapq:堆。會自動排序。
heap=[]
heapq.heappush(heap,(2,'two'))
heapq.heappush(heap,(1,'one'))

(3)base64模塊:對二進位數據編碼,避免顯示亂碼(用記事本打開exe、jpg、pdf這些文件時,我們都會看到一大堆亂碼);
Base64是把3位元組一組變為4位元組一組,所以,Base64編碼的長度永遠是4的倍數;
base64是一種任意二進位到文本字元串的編碼方法,常用於在URL、Cookie、網頁中傳輸少量二進位數據。
base64.b64encode(b'') #編碼
base64.b64decode(b'') #解碼
base64.urlsafe_b64encode(b'') #對於URL二進位編碼時,把字元+和/分別變成-和_
base64.urlsafe_b64decode(b'')

(4)hashlib哈希演算法模塊(加密函數)
1、hashlib.md5()。MD5是最常見的摘要演算法,速度很快,生成結果是一個32位的十六進位字元串表示。如:
import hashlib
md5=hashlib.md5('how to use md5 in python hashlib?'.encode())
print(md5.hexdigest())

2、hashlib.shal()。與md5()用法一致。

(5)itertools模塊:操作可迭代對象,返回值不是list,而是Iterator,只能用“for”迴圈迭代的時候才真正計算。
1、count類。無限計數。
2、cycle類。無限迴圈每個元素。
3、repeat類。重覆整個參數。
4、chain類。將迭代對象串聯。
5、groupby類。把迭代器中相鄰的重覆元素挑出來放在一起。

(6)contextlib模塊:上下文。
@contextmanager,上下文裝飾器。

(7)關於XML。
操作XML有兩種方法:DOM和SAX。
DOM方法會把整個XML讀入記憶體,解析為樹,因此占用記憶體大,解析慢,優點是可以任意遍歷樹的節點。
SAX方法是流模式,邊讀邊解析,占用記憶體小,解析快,缺點是我們需要自己處理事件。
正常情況下,優先考慮SAX,因為DOM實在太占記憶體。

ElementTree模塊:XML元素樹,解析和寫入節點。
tree=ElementTree() #實例元素樹
root=tree.parse(fh) #獲取根節點
print(root)
stations=set({})
for ele in tree.getiterator('station_name'): #迭代某個節點
stations.add(ele.text)

(8)關於HTMLParser。
HTML本質上是XML的子集,但是HTML的語法沒有XML那麼嚴格,所以不能用標準的DOM或SAX來解析HTML。Python提供了HTMLParser來非常方便地解析HTML。

(9)urllib模塊:用於操作URL地址(屬於上下文,所以可以用 with...as... 語句)。
request子模塊,Request類。
1、GET
請求指定的網址:with urlopen('https://api.douban.com') as url:
print(url.status,url.reason)
print(url.getheaders())

模擬瀏覽器,添加HHTP頭:req = Request('http://www.douban.com/', headers={'User-Agent': 'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25'})
with urlopen(req) as url:
print(url.getheaders())
print(url.read().decode())

2、POST
如果要以POST發送一個請求,只需要把urlopen()中參數data以bytes形式傳入。
email=input('微博賬號:')
passwd=input('密碼:')
login_info=parse.urlencode({
'username':email,
'password':passwd,
'entry': 'mweibo',
'client_id': '',
'savestate': '1',
'ec': '',
'pagerefer': 'https://passport.weibo.cn/signin/welcome?entry=mweibo&r=http%3A%2F%2Fm.weibo.cn%2F'
})
req=Request('https://passport.weibo.cn/sso/login')
req.add_header('Origin', 'https://passport.weibo.cn')
req.add_header('User-Agent', 'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25')
req.add_header('Referer', 'https://passport.weibo.cn/signin/login?entry=mweibo&res=wel&wm=3349&r=http%3A%2F%2Fm.weibo.cn%2F')
with urlopen(req,data=login_info.encode()) as url:
print(url.status,url.read())

83、第三方庫。基本上,所有的第三方模塊都會在PyPI-the Python Package Index上註冊,只要找到對應的模塊名字,即可用“pip install modulename”或“easy_install modulename”安裝。
(1)pillow,圖像處理庫。
在命令行cmd直接輸入:pip install pillow 進行安裝。例,製作驗證碼:
from PIL import Image #導入pillow
def rand_draw_color():
return (random.randint(64,255),random.randint(64,255),random.randint(64,255))
def font_color():
return (random.randint(32,255),random.randint(32,255),random.randint(32,255))
def rand_char():
return chr(random.randint(65,90))
#圖像的尺寸
width=60*4
height=60
#創建圖像
img=Image.new('RGB',(width,height),color=(255,255,255))
#創建畫布(用於塗鴉)
draw=ImageDraw.Draw(img)
#填充畫布顏色,按像素填充
for draw_color_x in range(width):
for draw_color_y in range(height):
draw.point((draw_color_x,draw_color_y),fill=rand_draw_color())
#輸出4個隨機字元
for char_count in range(4):
draw.text((60*char_count+15,10),rand_char(),fill=font_color(),font=ImageFont.truetype('Font/msyh.ttf',36))
#模糊處理
img=img.filter(ImageFilter.GaussianBlur) #這裡必須做賦值處理
img.save('Images/vali_code.jpg','JPEG')

(2)virtualenv為應用提供了隔離的Python運行環境,解決了不同應用間多版本的衝突問題。

84、圖形界面(GUI),調用內置的Tkinter。。例:
from tkinter import *
class AppTK(Frame):
def __init__(self):
super().__init__()
def createWidg(self):
self.nameInput=Entry()
self.nameInput.pack()
self.alertButt=Button(text='確定',command=self.alertFunc)
self.alertButt.pack()
def alertFunc(self):
info=self.nameInput.get() or '空值'
messagebox.showinfo('消息','歡迎,'+info)
app=AppTK()
app.createWidg()
app.master.title('提示')
app.mainloop()

85、網路編程。
IP地址實際上是一個32位整數(稱為IPv4),以字元串表示的IP地址如192.168.0.1實際上是把32位整數按8位分組後的數字表示,目的是便於閱讀。
IPv6地址實際上是一個128位整數,它是目前使用的IPv4的升級版,以字元串表示類似於2001:0db8:85a3:0042:1000:8a2e:0370:7334。
TCP協議則是建立在IP協議之上的。TCP協議負責在兩台電腦之間建立可靠連接,保證數據包按順序到達。
埠有什麼作用?在兩台電腦通信時,只發IP地址是不夠的,因為同一臺電腦上跑著多個網路程式。

(1)TCP協議編程。使用import socket。創建TCP連接時,主動發起連接的叫客戶端,被動響應連接的叫伺服器。
80埠是Web服務的標準埠。SMTP服務是25埠,FTP服務是21埠,等等。埠號小於1024的是Internet標準服務的埠,埠號大於1024的,可以任意使用。
備註:發送和接收的數據是位元組,需要編碼和解碼。
客戶端:必須知道伺服器的IP地址和埠號。
#建議網路連接
sock=socket()
sock.connect(('www.sina.com.cn',80))
sock.send(b'GET/ HTTP/1.1\r\nHost:www.sina.com.cn\r\nConnection:close\r\n\r\n') #註意HTTP協議格式
#接收數據,使用永迴圈
buffer=[]
while True:
data=sock.recv(1024)
if data:
buffer.append(data)
else:
break
data=b''.join(buffer)
sock.close()
#保存內容
header, html = data.split(b'\r\n\r\n', 1)
print(header.decode('utf-8'))
with open('sina.html', 'wb') as f:
f.write(html)

伺服器:伺服器進程首先要綁定一個埠並監聽來自其他客戶端的連接。
#####伺服器端#####
#1.建立連接,綁定伺服器
so_server=socket(type=SOCK_STREAM) #type=SOCK_STREAM表示TCP協議
so_server.bind(('127.0.0.1',9999))
so_server.listen(5) #監聽埠,入參數指定等待連接的最大數量
print('等待連接...')

#3.接收客戶端連接的函數,使用永迴圈
def tcp_link(so_link,addr_link):
print('正在連接',addr_link)
so_link.send('歡迎!'.encode()) #向客戶端發送send()
while True:
data=so_link.recv(1024) #接收客戶端數據recv()
if not data or data.decode()=='exit':
break
so_link.send('你好,%s'.encode() %data)
so_link.close()
print('關閉連接', addr_link)

#2.伺服器通過一個永久迴圈來接受客戶端的連接
while True:
so,addr=so_server.accept() #接受客戶端連接
thr=Thread(target=tcp_link, args=(so, addr)) #線程處理連接
thr.start()
thr.join()


#####客戶端#####
from socket import socket
so_client=socket(type=SOCK_STREAM)
so_client.connect(('127.0.0.1',9999)) #連接伺服器
print(so_client.recv(1024).decode()) #接收伺服器“歡迎”數據。如果數據大,則採用緩存append
for data in ['Michael', 'Tracy', 'Sarah']: #向伺服器發數據,並接收返回數據
so_client.send(data.encode())
print(so_client.recv(1024).decode())
so_client.send('exit'.encode())
so_client.close()

(2)UDP協議編程。UDP是面向無連接的協議,不可靠。優點是和TCP比,速度快。
伺服器不需要監聽(listen()),客戶端不需要連接(connect())。
#####伺服器端#####
so=socket(type=SOCK_DGRAM)
so.bind(('127.0.0.1',9999))
def udp_accept():
while True:
data,addr=so.recvfrom(1024)
print('請求客戶端:',addr)
so.sendto('你好,%s'.encode() %data,addr)
thr=Thread(target=udp_accept)
thr.start()
thr.join()

#####客戶端#####
so=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for data in ['Michael', 'Tracy', 'Sarah']:
so.sendto(data.encode(),('127.0.0.1',9999))
print((so.recv(1024)).decode())
so.close()

86、發郵件協議:“SMTP”:Simple Mail Transfer Protocol
收郵件協議:“POP3”:Post Office Protoco
“IMAP”:Internet Message Access Protocol

87、資料庫編程。
關係型:閉源收費資料庫:Oracle、DB2; 開源免費資料庫:MySQL、SQLite(嵌入式資料庫,輕量,Python內置)
1、SQLite
#連接資料庫,若無則新建
conn=sqlite3.connect('test.db')
#創建游標,實際操作者
cursor=conn.cursor()
cursor.execute(sql) #執行query
cursor.close() #關閉游標
conn.commit() #執行insert等操作後要調用commit()提交事務
conn.close() #關閉連接

2、MySQL
cmd安裝驅動:pip install pymysql, 例:
import pymysql
conn=pymysql.connect(user='root', password='0000', database='test',charset='utf8')
cursor=conn.cursor()
sql='select * from USER '
cursor.execute(sql)
data=cursor.fetchall()
print(data)
cursor.close()
conn.close()

3、MySQL框架:SQLAlchemy,把關係資料庫的表結構映射到class對象上(即ORM技術)。安裝SQLAlchemy:pip install sqlalchemy。例:

from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

Base=declarative_base() #先創建基類
class Pers(Base): #表的映射類
__tablename__='person' #表名
id=Column(primary_key=True) #要知道主鍵
name=Column()

engine=create_engine('mysql+pymysql://root:0000@localhost:3306/test') #連接庫,驅動是pymysql
Sess_maker=sessionmaker(engine) #登錄庫
session=Sess_maker()

person = session.query(Pers).filter(Pers.id=='1').one() #查詢數據
print(person.name)

# person=Pers(id='3',name='Nina3')
# session=Sess_maker()
# session.add(person) #插入數據
# session.commit()
# session.close()

88、WEB開發。
1)WEB伺服器(HTTP伺服器):與客戶端打交道,處理前端靜態內容(session、request、response、HTML、js、CSS等),如Apache、Nginx、IIS。只有Apache是純web伺服器!
2)應用伺服器:為應用程式處理後臺業務邏輯,客戶端應用程式可以調用的方法,生成動態內容,如 Weblogic(Java)、WebSphere(IBM)。
然而,現在大多數應用伺服器也包含了Web伺服器的功能,如Tomcat、IIS、WSGI。

1、HTTP請求方法:GET與POST,GET僅請求資源,POST會附帶用戶數據(區別於HTML表單的get、post方法)。一個HTTP請求只處理一個資源。
響應代碼:200表示成功,3xx表示重定向,4xx表示客戶端發送的請求有錯誤,5xx表示伺服器端處理時發生了錯誤。
web伺服器工作:接受HTTP請求、解析HTTP請求、發送HTTP響應。
HTTP GET請求的格式,每個Header一行一個,換行符是“ \r\n ”:
GET /path HTTP/1.1
Header1: Value1
Header2: Value2
Header3: Value3

HTTP POST請求的格式,包含body通過“ \r\n\r\n ”來分隔:
POST /path HTTP/1.1
Header1: Value1
Header2: Value2
Header3: Value3
body data goes here...

2、web過程:
a.瀏覽器發送一個HTTP請求;
b.伺服器收到請求,生成一個HTML文檔;
c.伺服器把HTML文檔作為HTTP響應的Body發送給瀏覽器;
d.瀏覽器收到HTTP響應,從HTTP Body取出HTML文檔並顯示。

3、HTML定義了頁面的內容,CSS來控制頁面元素的樣式,而JavaScript負責頁面的交互邏輯。

4、WSGI伺服器:Python定義的Web伺服器和應用伺服器之間的一種通用介面。例:
def app(request,response): # web app用來處理請求和響應。request處理請求信息;response處理響應信息。
response('200 OK',[('Content-Type','text/html')])
body='<h1>Hello,world!%s</h1>' %(request['PATH_INFO'][1:])
return [body.encode()] #返回列表類型

httpd=make_server('localhost',2017,app)
httpd.serve_forever()

89、web服務框架:很多框架都自帶了WSGI,比如 Flask,webpy,Django、CherryPy等。
flask:需pip install flask,例:
app=Flask(__name__)
#獲取首頁
@app.route('/',methods=['GET'])
def home():
return '<h1>HOME</h1>'

90、MVC模式:M(模型) ——業務數據(或業務邏輯),這是應用程式的主體;
V(視圖) ——用戶交互界面(模板);
C(控制器)——接收來自界面的請求,處理用戶界面數據顯示。

91、非同步IO(協程(coroutine)):一個主線程,子程式中斷,可以同時處理多個IO請求,並且沒有切換線程的操作,效率高。
能取代多線程和多進程。如讀寫磁碟文件、網路數據的非同步問題。
多線程和多進程的模型雖然解決了非同步問題,但是系統不能無上限地增加線程,系統切換線程的開銷也很大。
sync:同步;
async:非同步。

92、非同步IO庫:asyncio,編程模型是一個消息迴圈,從asyncio模塊中直接獲取一個EventLoop的引用,然後把需要執行的協程扔到EventLoop中執行。
1)asyncio提供了完善的非同步IO支持; #Python3.4開始
2)非同步操作需要在coroutine(如函數)中通過yield from完成;
3)多個coroutine(如函數)可以封裝成一組Task然後併發執行。
例:
import asyncio
import threading

@asyncio.coroutine
def hellopf():
print('Hello!!',threading.current_thread())
yield from asyncio.sleep(2)
print('World!!',threading.current_thread())
task=[hellopf(),hellopf()]
loop=asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(task))
loop.close()

# Python3.5變化:
a.把@asyncio.coroutine替換為async;
b.把yield from替換為await。

(更新中...)


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 眾所周知,我們在寫程式的時候,好習慣是在重要的代碼打上日誌。以便監控程式運行的性能和記錄可能發生的錯誤。但是,如果日誌是基於同步IO文件操作,那麼就必須考慮到訪問總次數或併發數目。如果總次數或併發數目非常大,比如10W或者1K/s 或更多,那麼就要註意IO的同步性能對程式速度的拖慢效應了。 這個時候 ...
  • 本期同樣帶給大家分享的是阿笨在實際工作中遇到的真實業務場景,請跟隨阿笨的視角去如何採用基於開源組件SmartThreadPool線程池技術實現多任務批量處理。在工作中您是否遇到過如何快速高效的處理Job任務列表、如何通過多線程批量處理訂單、如何多線程群發簡訊、如何批量上傳圖片到遠程圖片伺服器或者雲存... ...
  • 最近單位開發一個項目,其中需要用到自動升級功能。因為自動升級是一個比較常用的功能,可能會在很多程式中用到,於是,我就想寫一個自動升級的組件,在應用程式中,只需要引用這個自動升級組件,並添加少量代碼,即可實現自動升級功能。因為我們的程式中可能包含多個類型的文件,比如exe、dll、 config、xm... ...
  • 本期同樣帶給大家分享的是阿笨在實際工作中遇到的真實業務場景,請跟隨阿笨的視角去如何實現採用微軟的ASP.NET OWIN技術承載WebAPI服務,如果您對本期的教程內容感興趣,那麼請允許讓阿笨帶著大家一起學習吧! 廢話不多說,直接上乾貨,我們不生產乾貨,我們只是乾貨的搬運工。 ...
  • 註解是jdk1.5新增的特性.大家都知道,jdk1.5在java的發展史上有著劃時代的意義.而註解的出現,在某種程度上顛覆了框架的設計.比如,spring在註解出現後,改善了原先五大組件的模式,增加了基於註解的實現方式.現在重點講講註解的使用. 元註解: jdk1.5定義了4個元註解,元註解的作用是 ...
  • 字元串轉換成其他基本類型,以及包裝類的自動裝箱、拆箱 ...
  • Desert King Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 26009 Accepted: 7219 Description David the Great has just become the king of a ...
  • 我這次使用的ThinkPHP版本是:3.2.3版本,還有會使用到一個彈出層插件,叫 layer,官網地址是:http://layer.layui.com/。廢話不多說,進入擼碼環節。 1、通用方法編寫 這個是後端公共方法,現在暫時寫兩個方法,再往後開發想到有需要的話,就會繼續添加更多的公共方法。 公 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...