python基礎知識總結之一
1.字符集問題
windows下面儘量用#coding:gbk
Linux下面儘量用#coding:utf-8
2.什麼是序列
序列是指有序和無序的資料結構
包括:字串,列表,元組,字典,集合
3.程式設計規範
命名規範:
類定義用駝峰式 TestCase
其他用小寫字元加下劃線 test_case
常量全部用大寫
註釋的兩種方式:
單行註釋用#
類和物件的docstring用”“” “”“
import順序:
標準庫,第三方庫,自定義庫
不同型別的庫中間空一行
空行:
類與函式之間空兩行
函式與函式之間空一行
函式中,邏輯程式碼段之間空一行
4.庫、包、模組的概念
庫:python的一個專案
包:包含__init__.py檔案的資料夾
模組:以.py為結尾的檔案
py2中,包裡面必須有__init__.py檔案,否則直譯器無法識別這個包,也就是包下面的.py檔案,外部無法呼叫。
5.import匯入模組搜尋順序
import匯入的時候,針對模組名,首先搜尋當前目錄,然後查詢標準庫,最後查詢第三方庫。
6.__init__.py檔案的作用
python中__init__.py檔案的作用:Python中每個模組的包下面都有一個__init__.py檔案,有了這個檔案,我們才能匯入這個包下面的module。
7.如何設定環境變數
windows環境:我的電腦-屬性-高階系統設定-高階-環境變數,修改PATH,新增;$PYTHON_INSTALL_DIR(自己改)
Linux環境:export PATH=…….
8.第三方庫安裝位置 $PYTHON_INSTALL_DIR\Lib\site-packages
9.檢視內建函式:dir(builtins)
10.type和isinstance()函式
Python在定義變數的時候不用指明具體的的型別,直譯器會在執行的時候會自動檢查變數的型別,並根據需要進行隱式的型別轉化。
因為Python是動態語言,所以一般情況下是不推薦進行型別轉化的。
比如”+”操作時,如果加號兩邊是資料就進行加法操作,如果兩邊是字串就進行字串連線操作,如果兩邊是列表就進行合併操作,甚至可以進行復數的運算。直譯器會在執行時根據兩邊的變數的型別呼叫不同的內部方法。當加號兩邊的變數型別不一樣的時候,又不能進行型別轉化,就會丟擲TypeError的異常。
但是在實際的開發中,為了提高程式碼的健壯性,我們還是需要進行型別檢查的。而進行型別檢查首先想到的就是用type(),比如使用type判斷一個int型別。
對於內建的基本型別來說,使用tpye來檢查是沒有問題的。
可是當應用到其他場合的時候,type就顯得不可靠了。比如:
class A():
pass
class B():
pass
a = A()
b = B()
print(type(a) is type(b))
程式碼的輸出結果: True1234567891011
此例中type的判斷顯然是有問題的。
這個時候我們就需要使用isinstance來進行型別檢查。
isinstance(object, classinfo)1
object表示例項,classinfo可以是直接或間接類名、基本型別或者有它們組成的元組。
>>> isinstance(2, float)
False
>>> isinstance('a', (str, unicode))
True
>>> isinstance((2, 3), (str, list, tuple))
True123456
可以參考此博文:https://www.jianshu.com/p/7ef549503c93
11.字典這個序列,以key作為序列中的每一項
>>> list({1:2,3:4})
[1, 3]12
12.函式返回值的問題
def test():
print('lijingkuan')
print(test())1234
返回值為
lijingkuan
None12
為什麼呢?
原因是:
字串’lijingkuan’是test()函式列印的,而None是print()函式列印的,
None是test()函式的返回值。
修改一下
def test():
print('lijingkuan')
return 123
print(test())12345
則輸出結果變為
lijingkuan
12312
如果不想列印那個None,就直接執行test()就行了,不要print。
13.raw_input函式
接受使用者輸入,返回字串
— 重要,返回的是字串,不是數字或者其他型別
14.list可以用來儲存任何型別的物件,不強制要求型別相同,是有序的。
15.type和isinstance的區別???
16.list的高階特性
增刪改查、排序
增:
append,extend,insert
append和extend的區別?
append是往列表中新增一個值,extend是增加一個序列。
列表a+b會生成一個新的列表,原來的a和b不會變化。
一般寫作 c=a+b
a.extend(b)會修改列表a,與a+b有區別。
a.append(b),會將b當成一個值去對待,而不是當成一個列表。
例如:
a=[1,2,3],b=[4,5,6]
a.extend(b) = [1,2,3,4,5,6]
a.append(b)=[1,2,3,[4,5,6]]123
因此:
append往列表中新增元素,該元素可以是任何形式的資料結構或物件,新增的物件作為列表中的一個元素,放到最後一位。
extend用於在列表末尾一次性追加另一個序列中的多個值,不是把物件整個新增,而是拿出每一項來新增。
>>> a=[1,2,3]
>>> b="abc"
>>> a.extend(b)
>>> a
[1, 2, 3, 'a', 'b', 'c'] --字串也是序列
>>> c={'f':1,7:9}
>>> a.extend(c)
>>> a
[1, 2, 3, 'a', 'b', 'c', 'f', 7]
-- 字典也是序列
-- 當字典作為一個序列的時候,那麼序列的每一項指的是字典的key,不包括value。1234567891011
insert:往列表中新增元素,兩個引數,第一個引數表示insert的位置,第二個引數表示insert的引數的value。
刪:
remove,pop
>>> a
[1, 2, 3, 'a', 'b', 'c', 'f', 7]
>>>
>>>
>>> a.remove(2)
>>> a
[1, 3, 'a', 'b', 'c', 'f', 7]
>>>
>>> a.pop(2)
'a'
>>> a
[1, 3, 'b', 'c', 'f', 7]123456789101112
remove刪除的是具體的value,沒有返回值。
pop刪除的是索引對應的value,並將刪除的元素返回。
如果pop()不加引數,刪除的是最後一個元素。
pop(0),刪除第一個元素
堆疊:坑,先進後出,通過pop()實現
佇列:通道,先進先出,通過pop(0)實現
改:
通過賦值去完成(通過索引定位):
a[2]=5
查:
1.通過索引
2.通過index去進行查詢
3.獲取某個值在列表中的位置
>>> a
[1, 3, 'b', 'c', 'f', 7]
>>> a[1]
3
>>> a.index('f')
4123456
排序:
sort,sorted
sort不改變列表,sorted改變列表
sort是列表的方法,對列表中value重新排序,sorted是內建函式,對序列進行排序,輸出排序後的序列。
>>> a=[6,2,1,3,9,8]
>>> sorted(a)
[1, 2, 3, 6, 8, 9]
>>> a
[6, 2, 1, 3, 9, 8]
>>> a.sort()
>>> a
[1, 2, 3, 6, 8, 9]12345678
17.list兩種遍歷方式(非常重要)
for item in _list
for index,item in enumerate(_list)
>>> a=[5,2,1]
>>> for index,item in enumerate(a):
... print(index,item)
...
0 5
1 2
2 11234567
18.列表推導式
格式1:【輸出 for xx in 序列 if 條件表示式】
一句話完成列表遍歷,在迴圈中把滿足某些條件的取出來。
求1-100內能同時除盡2和3的整數
--列出10以內的偶數
>>> [x for x in range(0,11) if x%2==0]
[0, 2, 4, 6, 8, 10]
--求1-100內能同時除盡2和3的整數
>>> [x for x in range(1,101) if (x%2==0 and x%3==0)]
[6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96]1234567
格式2:【輸出 if 條件 else 表示式 for xx in 序列】
一句話完成列表編列,在迴圈中把滿足和不滿足某些條件的取出來做處理。
--將10以內的奇數平方,偶數減半
>>> [i*i if i%2==1 else int(i/2) for i in range(1,11)]
[1, 1, 9, 2, 25, 3, 49, 4, 81, 5]123
18.__pycache__資料夾儲存之前執行過的.py檔案生成的pyc檔案,如果下次執行.py檔案時發現.py檔案未作修改,則直接去pycache裡面執行pyc檔案,優化python的執行效率。
19.python3中的range相當於python2中的xrange。
20.input和raw_input的區別?
21.列表的切片問題
列表的切片是前閉後開的,即a[1:4],包含1,不包含4。(索引是從0開始的)
22.字串split()函式
split() 方法語法:
str.split(str="", num=string.count(str)).
引數
str -- 分隔符,預設為所有的空字元,包括空格、換行(\n)、製表符(\t)等。
num -- 分割次數。
返回值
返回分割後的字串列表。12345678
split()和split(’ ‘)執行結果的差別
split()將空格,換行符,製表符等作為分隔符,而split(’ ‘)只是將空格作為分隔符。
23.字串比較,in 的用法
兩種情況:
字串情況下最小單位為字元
s = "abc 123"
ret = "ab" in s
print (ret)123
陣列情況下最小單位是每個字串
li = ["tom","rose","jack"]
ret = "to" not in li
print (ret)123
24.字典
用大括號包括,用逗號分隔每個鍵值對,鍵值對之間用冒號連線
鍵是不可改變的資料結構(不是隨便一個型別的資料都可以當鍵的),值可以是任意的物件
a={}
a=dict()
使用:
普通查詢,引數校驗:
字典的訪問是通過key去取value
a={1:2,’haha’:e}
a[‘haha’] 如果沒有這個key,執行會報錯,可用於引數校驗
a.get(‘haha’) 如果沒有這個key,返回值為null
注意兩者的區別。
增加、修改
直接賦值,setdefault,update
a[‘test’]=’diyige’ 既可以增加,又可以修改
a.setdefault() 增加一個新的key value,如果key存在,則value不更新
a.update(k,v)效果跟直接賦值一樣
setdefault()用法:
語法
setdefault()方法語法:
dict.setdefault(key, default=None)
引數
key -- 查詢的鍵值。
default -- 鍵不存在時,設定的預設鍵值。
返回值
如果字典中包含有給定鍵,則返回該鍵對應的值,否則返回為該鍵設定的值。123456789
刪除:
pop(key)
刪除指定給定鍵所對應的值,返回這個值並從字典中把它移除。注意字典pop()方法與列表pop()方法作用完全不同。
字典的遍歷:兩種(三種)
(1)for item in _dict:
print item
輸出的是key,不輸出value,因為遍歷的時候是吧字典當序列遍歷
(2)for k,v in a.items():
print(k,v)
(3) for item in a.values() –只遍歷values,基本用不到
25.列表中的字串過濾問題
startwith()
描述
Python startswith() 方法用於檢查字串是否是以指定子字串開頭,如果是則返回 True,否則返回 False。
如果引數 beg 和 end 指定值,則在指定範圍內檢查。
語法
startswith()方法語法:
str.startswith(str, beg=0,end=len(string));
引數
str -- 檢測的字串。
strbeg -- 可選引數用於設定字串檢測的起始位置。
strend -- 可選引數用於設定字串檢測的結束位置。
返回值
如果檢測到字串則返回True,否則返回False。1234567891011121314
內建函式:filter(function_name,sequence)
將sequence中的每一項作為引數傳遞給function,即function(item)
在python2中,將符合條件的(執行結果為True),返回list ,tuple或者dict(需要驗證,是否只返回列表),視sequence的型別而定,迴圈遍歷取出。
在python3中,將執行結果為True的item,返回一個filter的物件,使用迴圈遍歷取結果。
26.元組
列表是[],元組是(),都是有序的,元組建立之後無法修改,而列表是可以修改的。
元組的表示是逗號‘,’不是括號(),也就是說,不是加了()就是元組,而是要有,逗號,具體解釋的舉例如下:
>>> a=(1,2,3)
>>> type(a)
<class 'tuple'>
>>>
>>> a= 1,2,3
>>> type(a)
<class 'tuple'>
>>> a=(1)
>>> b=(1,)
>>> type(a)
<class 'int'>
>>> type(b)
<class 'tuple'>
>>> c=1,
>>> type(c)
<class 'tuple'>1234567891011121314151617
元組和列表一樣,通過下標訪問。
元組的使用場景:
1.函式返回多項
return a,b
2.if a in b(b是一個元組)
或者if a in (‘test1’,’hello’,’gaga’,)
– 參考前面提到過的 in 的使用
27.集合 set
描述元素種類的一種無序序列,內建函式set
1.沒有重複項
2.無序
>>> a='hello'
>>> set(a)
{'e', 'l', 'o', 'h'}
>>> a=set({1:2,4:5})
>>> a
{1, 4}1234567
集合和列表的轉換
集合的一些運算,其他的序列可能沒有,普通列表可能需要使用集合的特徵進行運算,比如求兩個列表的交集,差集,並集等等
>>> a=[1,2,3,4,5,6,7]
>>> b=[5,7,9]
>>>
>>> set(a) & set(b)
{5, 7}
>>>
>>> set(a) | set(b)
{1, 2, 3, 4, 5, 6, 7, 9}
>>>
>>> set(a) - set(b)
{1, 2, 3, 4, 6}1234567891011
應用:比如IP去重
set作為序列遍歷
for item in set:
28.函式
排名問題
29.字串前面加 ‘r’ 的作用
開啟檔案時open(r’d:\hello\hello.txt’)
不加r會報錯,因為系統認為\是轉義符
30.函式
def func_name(paras):
return
引數有幾種?
普通引數 ,預設引數, 可變長引數
* args代表元組,會把所有沒有指定key的引數,把這一類引數放到一個元組中
* * kwargs代表字典,會把所有指定key的引數,放到字典中
>>> def test_args(*args, **kwargs):
... print(args,kwargs)
...
>>> test_args(5,c=8)
(5,) {'c': 8}
>>> test_args(5,8,c=8,d=9)
(5, 8) {'c': 8, 'd': 9}
>>> def test_args(*args, **kwargs):
... return args,kwargs
...
>>> test_args(5,8,c=8,d=9)
((5, 8), {'c': 8, 'd': 9})
--上面的返回結果中多了最外邊的兩個括號,原因是return返回的是元組(元組的應用之一)1234567891011121314
31.深拷貝
迴圈遍歷中的刪除問題
將列表中字串的項刪除
_list = [1,'aa','123','test',8,9,7]
def filter_str(item):
if isinstance(item,str):
return False
else:
return True
# return not isinstance(item,str):
ret = []
rst = filter(filter_str, _list)
for item in rst:
ret.append(item)
print(ret)1234567891011121314
深度拷貝(補充程式碼在github上deep_copy.py)
32.巢狀函式 & 匿名函式
可程式設計引數 -> 函數語言程式設計 -> 巢狀函式 -> 閉包 -> 裝飾器
def test(m,n):
return m+n
def func(func_name, *args, **kwargs):
ret = func_name(*args, **kwargs):
return ret+1
print(test(8,9))
print(func(test,8,9))123456789
巢狀函式(子函式):函式體裡面包含另一個函式的完整定義
應用場景:一個函式中有一小段邏輯被多次呼叫
閉包,裝飾器
子函式能夠呼叫父函式的區域性變數,父函式無法呼叫子函式的區域性變數
參考github中qiantao*.py
匿名函式(lambda函式):
定義:lambda跟一個或多個引數,跟著冒號,接著是一個表示式。
lambda是一個關鍵字,lambda冒號前邊是引數,後邊返回結果
形式:lambda x,y:x+y
應用場景:
函數語言程式設計中,函式名本應由對應的實現邏輯,對於簡單的邏輯,可以用一個lambda來表示。
更多的應用,是和一些內建函式進行搭配,比如filter,map,sorted
舉例:
排名問題(下) 參考github上paiming.py
>>> func_name = lambda x,y : x+y
>>> func_name
<function <lambda> at 0x0000000001D31E18> --注意:返回的是函式名
>>> func_name(1,2)
3
>>>
效果和下面的相同
def add(x, y):
return x,y
add(1,2)
相同點,區別是什麼?
相同點:
完成的作用相似
區別:
lambda返回的是一個函式名
正常函式返回的是結果12345678910111213141516
33.內建函式 map
map(function, sequence)
定義:對sequence中的item依次執行function(item),將執行結果返回一個map迭代物件,可以通過list放入列表中
舉例:輸出1到15的所有數的平方
參考github中pingfang.py
34.函數語言程式設計
定義:對別的函式進行封裝,運算,操作的函式
學習目的:
(1)需要對別的函式進行封裝
(2)看原始碼(看別人的程式碼)
引數:
(1)支援傳別的函式名
(2)任意引數*args ,**kwargs
應用場景:
(1)對一件事進行封裝
(2)閉包、裝飾器(以後講)
標識:引數是其他函式的函式名
典型的使用了函數語言程式設計的內建函式:sorted,map,filter
35.直譯器載入指令碼順序
執行指令碼中的某個函式,例如run(),可以使用以下兩種寫法,區別是什麼?
(1)
if __name__ == "__main__":
run()
(2)
run()1234567
參看下面的指令碼:
#coding:gbk
#python直譯器載入檔案的順序
var1 = 1
var2 = 2
def test():
print("執行test")
def test1():
print("執行test1")
print(var1)
test1()
if __name__ == '__main__':
print(var2)
test()
我原本以為會先執行main函式,再執行指令碼中其他的函式,輸出
2
執行test
1
執行test1
但實際執行結果是,先執行前面的程式碼,最後執行的main,輸出
1
執行test1
2
執行test123456789101112131415161718192021222324252627282930
結論:
程式程式碼入口,並不是程式開始執行時第一個執行的。在其他語言中也是同樣的道理。
順序:
(1)載入import模組
(2)載入全域性變數,全域性物件
(3)載入函式名(註冊函式名,不執行函式體)。如果有函式執行的話,就直接執行。
(4)if name == ‘main‘:
因為:
全域性變數:存放在記憶體的靜態區域(對於你的整個程式碼可見)
區域性變數:存放在記憶體的棧中,函式執行完即銷燬
35.全域性變數global,區域性變數
全域性變數:位置在全域性區域的變數
區域性變數:在函式內的變數
函式的作用域:
L (Local) 區域性作用域
G (Global) 全域性作用域
以 L –> G 的規則查詢,即:在區域性找不到,便會去區域性外的區域性找,在找不到就會去全域性找。
var = 12
def change_var():
# global var
var = 13
return var
print(change_var())
print(var)
輸出結果:
把global註釋掉,輸出 13,12
不註釋global,輸出13,13
可以通過在程式碼中新增print(id(var))來看看,各個變數var的地址是否相同
123456789101112131415
(1)如果函式中的變數與全域性變數重名的話,直譯器會把函式內的變數當成區域性變數,重名歸重名,但不是同一個變數
(2)如果想修改全域性變數,需要通過關鍵字global去宣告這個變數,這樣就可以在函式中修改全域性變數,一旦在函式中加了global,則這個函式中,這個名字的變數都是用的全域性變數
結論:自己定義的函式變數,不要跟全域性變數重名
36.內建函式eval,是把字串當做命令去執行
參考部落格:https://www.cnblogs.com/dadadechengzi/p/6149930.html
部落格中有更多示例
內建函式eval,是把字串當做命令去執行
將字串str當成有效的表示式來求值並返回計算結果
函式定義:
eval(expression, globals=None, locals=None)1
引數
expression:是一個參與計算的python表示式
globals: – 變數作用域,全域性名稱空間,是可選的引數,如果設定屬性不為None的話,就必須是dictionary物件了
locals也:– 變數作用域,區域性名稱空間,是一個可選的物件,如果設定屬性不為None的話,可以是任何map物件了
返回值
返回表示式計算結果。
eval(expression, globals=None, locals=None) — 官方文件中的解釋是,將字串str當成有效的表示式來求值並返回計算結果。globals和locals引數是可選的,如果提供了globals引數,那麼它必須是dictionary型別;如果提供了locals引數,那麼它可以是任意的map物件。
python是用名稱空間來記錄變數的軌跡的,名稱空間是一個dictionary,鍵是變數名,值是變數值。
當一行程式碼要使用變數 x 的值時,Python 會到所有可用的名字空間去查詢變數,按照如下順序:
1)區域性名字空間 - 特指當前函式或類的方法。如果函式定義了一個區域性變數 x, 或一個引數 x,Python 將使用它,然後停止搜尋。
2)全域性名字空間 - 特指當前的模組。如果模組定義了一個名為 x 的變數,函式或類,Python 將使用它然後停止搜尋。
3)內建名字空間 - 對每個模組都是全域性的。作為最後的嘗試,Python 將假設 x 是內建函式或變數。
python的全域性名字空間儲存在一個叫globals()的dict物件中;區域性名字空間儲存在一個叫locals()的dict物件中。我們可以用print (locals())來檢視該函式體內的所有變數名和變數值。
example:
a=1
g={'a':20}
eval("a+1",g) -- 這裡的g,就是全域性名字空間中的dict,g={'a':20}
-- 返回21
#test eval() and locals()
x = 1
y = 1
num1 = eval("x+y")
print (num1)
def g():
x = 2
y = 2
num3 = eval("x+y")
print (num3)
num2 = eval("x+y",globals())
#num2 = eval("x+y",globals(),locals())
print (num2)
g()
print locals()["x"]
print locals()["y"]
print globals()["x"]
print globals()["y"]
num1的值是2;num3的值也很好理解,是4;
num2的值呢?由於提供了globals()引數,那麼首先應當找全域性的x和y值,也就是都為1,那麼顯而易見,num2的值也是2。
如果註釋掉該句,執行下面一句呢?根據第3)點可知,結果為412345678910111213141516171819202122232425262728293031
eval函式的妙用:
eval函式就是實現list、dict、tuple與str之間的轉化
str函式把list,dict,tuple轉為為字串
字串轉換成列表
>>> a = "[[1,2], [3,4], [5,6], [7,8], [9,0]]"
>>> print(type(a))
<type 'str'>
>>> b = eval(a)
>>> type(b)
<type 'list'>
>>> print(b)
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 0]]
>>> 123456789
字串轉換成字典
>>> a = "{1: 'a', 2: 'b'}"
>>> print(type(a))
<type 'str'>
>>> b = eval(a)
>>> print(type(b))
<type 'dict'>
>>> print(b)
{1: 'a', 2: 'b'}
>>> 123456789
字串轉換成元組
>>> a = "([1,2], [3,4], [5,6], [7,8], (9,0))"
>>> print(type(a))
<type 'str'>
>>> b=eval(a)
>>> print(type(b))
<type 'tuple'>
>>> print(b)
([1, 2], [3, 4], [5, 6], [7, 8], (9, 0))
>>> 123456789
37.類的初步認識
class ClassName(FatherClass):
def __init__(self, class_args1):
self.class_args1 = class_args1
def class_func(self):
return123456
類例項 ==類物件
類引數寫在__init__裡(而不是寫在類名後面的括號裡,與其他語言不同)類後面的括號中寫的是類繼承的父類
類裡面所有的函式第一個引數要寫成self(不要問為什麼,照做就是了),凡是有self的函式,都是類例項函式
self其實是類例項物件
38.初始化 def __init__(self):
格式:
def __init__(self, a):
print(111)
self.a =a 123
當類初始化的時候,比如 a = A(‘ss’)
這個操作會打印出111,因為這個操作會執行init()函式
作用:類傳參的地方,例如a,呼叫的時候要傳入引數
用法:類例項屬性(例如self.a)在類的整個範圍內都可以使用
初始化例項物件的時候會執行__init__函式
39.類屬性 && 類例項屬性
類屬性,不需要初始化例項物件就可以使用
類例項屬性,在__init__()函式的列表中,需要有了例項物件之後才能呼叫
在程式載入過程中,類屬性和類定義,函式一樣,會被載入(註冊),類例項屬性不會,類例項方法會註冊,但不執行函式體。
類屬性的位置:在__init__函式的前面
類屬性使用場景:
類似於其他語言中的靜態引數,參看41
40.繼承
參考github指令碼class_inherint.py
41.類屬性的應用場景
參考 db_conn_class_property.py
42.訪問控制 public, protected,private
在Java,C++,以及PHP中都有對應的關鍵字,public,protected,private,但是在Python中卻沒有這些關鍵字來宣告類成員的訪問作用域。
在Python中是通過一套命名體系來識別成約的訪問範圍的
protected: _ 函式名開頭是一個下劃線
private: __ 函式名開頭是兩個下劃線
在python中所有的以字母開頭的成語名稱被python命名體系自動識別為public,單個下劃線開頭的成員被識別為protected,最後雙下劃線開頭的成員被識別為private。
另外,Python不支援諸如C++, Java的根據引數型別與數目的不同而進行的過載(overload),即只以函式名字做為函式身份的判斷,不會依據引數。而且如果出現多個同名函式(不論引數是否數目相同),則以最後一個為準(即後出現的函式將之前的同名函式覆蓋)。
參考 protected_private.py
43, python中的self其實就是類例項物件本身
參考 self.py
44.單例
監控程式,每次都要建立一個新的資料庫連線,監控頻繁情況下,需要建立很多很多連線,這個問題如何解決:
(1)使用前面提到的類屬性
(2)初始化一個類物件,放到全域性物件位置,其他想使用類的地方直接使用此物件
(3)單例(專業處理連線多的問題)
(4)資料庫連線池
單例模式,在類被執行的才連線,不想類屬性或者全域性類物件一樣,程式載入的時候就連線
是一個函式封裝
通過裝飾器的方式呼叫
場景:通過單例解決mysql等服務連線過多的問題
思路:
先判斷例項是否已經初始化
如果已經初始化了物件,直接使用初始化的物件
如果沒有,則初始化
參考singleton.py
45.閉包
閉包就是你呼叫了一個函式a,這個函式a返回了一個子函式名字b給你,這個返回的函式b就叫做閉包。
def a():
def b():
return 1
return b123456
所以,通俗的講,閉包就是,返回子函式名
作用:使用子函式之外的父函式的變數
參考 bibao.py
閉包到底是幹嘛的?一般用來做裝飾器
46.裝飾器
閉包+函數語言程式設計 = 裝飾器
例子參看第五課 6-裝飾器.avi
47.python中執行shell指令
執行狀態(執行成功或失敗)和執行結果:code,result
os.system() 返回code,result輸出在console中
>>>
>>> import os
>>> ret = os.system("free -m")
total used free shared buffers cached
Mem: 70619 9497 61122 0 212 1510
-/+ buffers/cache: 7774 62845
Swap: 4095 0 4095
>>> print(ret)
0
import commands
ret = commands.getoutput(shell指令或者指令碼)
code,ret = commands.getstatusoutput(shell指令或者指令碼)
命令不同,返回值的數量不同123456789101112131415
py3中,將commands模組融合在了subprocess模組中
48.執行緒
執行緒能否殺死?正常情況下是不能的。
執行緒安全問題如何解決?鎖。
多執行緒使用鎖的話,多執行緒是不是就成了串行了?只是某一時刻或某一部分序列
執行緒的作用是什麼?非同步、併發
Threading模組
需要掌握老師提供的指令碼
t = threading.Thread(target=func_name,args=[])
t.start
target是需要多執行緒執行的函式,args是函式的引數
原生呼叫的內部原理:
start觸發,run是真正執行的
預設是等待子執行緒退出,主執行緒才退出(程序在執行完所有程式碼時,子執行緒還未執行完,程序要等待子執行緒執行完再退出)
如果setDaemon(True),則不等待(要在子執行緒start之前設定,否則會報錯:RuntimeError: cannot set daemon status of active thread)
主執行緒退出後,子執行緒就沒了
#不帶引數
import time
import threading
def sleep():
time.sleep(5)
print('5 second')
return 'money'
t = threading.Thread(target=sleep)
#t.setDaemen(True)
t.start()
#帶引數
import time
import threading
def sleep(n):
time.sleep(n)
print('sleep %s second' % n)
return 'money'
t = threading.Thread(target=sleep, args=[3])
# t = threading.Thread(target=sleep, args=(3,)) 元組必須加逗號
t.start()
#如何獲得執行緒中的返回值?
#一般很難獲得執行緒中結果,但是如果工作中需要獲得結果,怎麼辦?
#這種需求很少
#1.寫入資料庫
#2.
# 原生執行緒的兩個缺點:
#1.傳參不得勁兒(用列表還好,用元組容易出錯(單個引數沒加逗號))
#2.函式的返回值無法獲取
1234567891011121314151617181920212223242526272829303132333435363738
join
使得執行緒阻塞到函式執行完成後,主執行緒才繼續進行
後者傳入一個引數,表明阻塞時間,超過該時間之後,就不阻塞了,可以繼續執行(不用等執行緒執行完成)
參考thread_join。py
使用場景是在多執行緒中,多個執行緒join,總執行時間,是幾個執行緒中執行時間最長的執行緒的執行時間。
鎖:
from threading import lock
lock = Lock()
lock.acquire()
lock.release()12345
執行緒池:
from concurent.futures import ThreadPoolExecutor
t = ThreadPoolExecutor(num)
t.submit(func_name)123
49.佇列
佇列的作用:
非同步:點贊業務(對於實時性要求不是很高,並且對資料庫操作)
系統解耦:訂單系統,發貨系統
緩衝流量:秒殺
在python中使用佇列
py2.7 Queue
py3.x queue
建立:queue.Queue(maxsize)
往佇列中存放元素:put(obj)
取元素:get() 按順序取,所以不需要引數
enpty()
import Queue
import time
q = Queue.Queue()
for i in range(10):
q.put(i)
while not q.empty():
print(q.get())
time.sleep(0.5)12345678910111213141516
50.異常處理
(1)異常拋錯機制
– 程式執行異常,直譯器會首先看當前的執行環境(函式或類)有沒有捕獲這個異常,有沒有try。
– 當函式裡沒有找到的話,它會將異常傳遞給上層的呼叫函式,看看那裡有沒有處理。
– 如果在最外層(全域性‘main’)還是沒有找到的話,直譯器就會退出,同時打印出traceback資訊在標準錯誤裡。
注:當異常發生的時候
– 程式碼異常,當前執行流終止,退出
– 異常資訊會列印在標準錯誤裡
怎麼樣才能不讓使用者看到報錯棧資訊,自己又能捕獲到報錯棧資訊呢?可以通過如下形式
import traceback
print(str(traceback.format_exc())) --可以儲存到一個變數裡面,記錄在日誌裡12
(2)異常資訊的組成
Traceback資訊 + 出錯型別 + 出錯原因
(3)捕獲異常的場景
– 允許程式碼發生某種型別的異常不需要終止程式碼,可以捕獲異常,繼續往下走。
– 建立資料庫連線或者其他的元件連線,使用完不管程式碼是否異常,都要關閉連線
– 執行緒中,程式碼要進行異常捕獲
– 指令碼:入口函式處
– 需要捕獲異常資訊用於展示:程式碼發生異常的時候,需要將異常資訊彙報給上層系統,例如程式碼部署指令碼,部署上百個機器,不可能通過登入機器去查詢報錯
(4)捕獲異常的5種方式
– try 。。。 except 。。。 最常用的一種
– try… except Exception as e: …print(e) 列印資訊不全,只打印報錯資訊
– try … except 特定的異常 print
– try…except … finally …
–