python基礎

目錄

python基礎python中的可變不可變類型數據類型列表元祖列表和元組經常使用函數字符串字典將兩個列表組合成字典集合字符編碼python2和python3的區別python2和python3中編碼轉換深拷貝、淺拷貝三元運算IO多路複用select、poll 、epoll(同步io)進程(資源分配的單位)、線程(操做系統調度的最小單位)、協程進程: 一個在運行起來的程序 系統給他分配資源 (運行在內存) 提資源進程說明進程池線程: 操做系統最小的調度單位,狀態保存在cpu的棧中經常使用方法join()方法isAlive()方法getName()方法setDaemon()方法線程鎖線程特性線程池協程: 微線程,纖程。 相似於單線程,不一樣於單線程,由於它能夠實現併發效果,由於有gevent(封裝了c語言的greenlet) 遇io自動切換(greenlet能夠檢測io),把這個io請求交給epoll猴子補丁協程優勢:缺點:高階函數1.map2.reduce3.filter4.sorted5.lambda(匿名函數)GIL全局解釋器鎖一、什麼是GIL二、GIL的做用三、GIL的影響四、如何避免GIL的影響5 爲何有時候加了GIL全局解釋器鎖 ,還要在加線程鎖?線程鎖裝飾器、迭代器、生成器迭代器 含有iternext方法 (包含next方法的可迭代對象就是迭代器)迭代器的定義:可迭代對象迭代器和可迭代對象關係:迭代器僅是一容器對象,它實現了迭代器協議。它有兩個基本方法iter方法會返回一個迭代器(iterator),所謂的迭代器就是具備next方法的對象。在調用next方法時,迭代器會返回它的下一個值,若是next方法被調用,但迭代器中沒有值能夠返就會引起一個StopIteration異常生成器yield運行機制手寫斐波那契迭代器生成器區別裝飾器裝飾器必須準尋得原則手寫三級裝飾器裝飾器的應用場景閉包閉包特色os和sys模塊的做用?面向對象面向對象方法靜態方法類方法屬性方法特殊(魔術)方法單例模式面向對象屬性公有屬性普通屬性私有屬性反射新式類和經典類的區別面向對象深度優先和廣度優先是什麼?三大特性:封裝,繼承,多態Encapsulation 封裝(隱藏實現細節)Inheritance 繼承(代碼重用)Polymorphism 多態(接口重用)垃圾回收機制1.引用計數原理優勢缺點2.標記-清除原理3.分代回收三種讀文件方式1.readline()2.readlines()3.read(size)tcp udptcp三次握手四次揮手TCP與UDP比較Websocket數據結構棧的定義棧的特色棧的基本操做棧的應用場景隊列隊列的定義隊列的使用方法鏈表單鏈表鏈表反轉雙鏈表單向循環鏈表數組python中list與數組比較字典實現原理哈希表Python經常使用模塊subprocesssubprocess原理subprocess.Popen()subprocess.PIPE paramikoParamiko模塊做用re經常使用正則表達式符號匹配時忽略大小寫syssys基本方法ostimetime()模塊中的重要函數**time()模塊時間轉換**datetimehtml

 

python基礎

python中的可變不可變類型

可變數據類型:列表、字典python

不可變數據類型:數字、字符串、元組linux

數據類型

列表

append 用於在列表末尾追加新的對象ios

count 方法統計某個元素在列表中出現的次數正則表達式


a = ['aa','bb','cc','aa','aa']
print(a.count('aa'))   #the result : 3

extend方法能夠在列表的末尾一次性追加另外一個序列中的多個值shell


a = [1,2,3]
b = [4,5,6]
a.extend(b)   #the result :[1, 2, 3, 4, 5, 6]

index 函數用於從列表中找出某個值第一個匹配項的索引位置編程

insert 方法用於將對象插入到列表中 結合下標使用windows

pop 方法會移除列表中的一個元素(默認是最後一個),而且返回該元素的值數組

remove 方法用於移除列表中某個值的第一個匹配項瀏覽器


a = ['aa','bb','cc','aa']
a.remove('aa')     #the result : ['bb', 'cc', 'aa']

reverse 方法將列表中的元素反向存放

sort 方法用於對列表進行排序

enumrate 和for循環差很少 只是能獲取下標的同時還能獲取item


li = [11,22,33]
for k,v in enumerate(li, 1):
  print(k,v)
#打印結果以下:
1 11
2 22
3 33

元祖

元祖和列表同樣、只不過元祖是隻讀列表

列表和元組經常使用函數

  com(x,y)       比較兩個值

  len(seq)       返回序列的長度

  list(seq)       把序列轉換成列表

  max(args)       返回序列或者參數集合中得最大值

  min(args)       返回序列或者參數集合中的最小值

  reversed(seq)   對序列進行反向迭代

  sorted(seq)     返回已經排列的包含seq 全部元素的列表

  tuple(seq)     把序列轉換成元組

字符串

使用百分號(%)字符串格式化

使用format字符串格式化

find方法能夠在一個較長的字符串中查找子串,他返回子串所在位置的最左端索引,若是沒有找到則返回-1


a = 'abcdefghijk'
print(a.find('abc'))                 #the result : 0
print(a.find('abc',10,100))         #the result : 11 指定查找的起始和結束查找位置

join方法 是很是重要的字符串方法,鏈接序列中的元素,而且須要被鏈接的元素都必須是字符串。


a = ['1','2','3']
print('+'.join(a))       # 1+2+3

split方法 是很是重要的字符串,用來將字符串分割成序列


print('1+2+3+4'.split('+'))       # ['1', '2', '3', '4']

strip 方法返回去除首位空格(不包括內部)的字符串


print(" test   test   ".strip())       #「test   test」

replace方法 返回某字符串全部匹配項均被替換以後獲得字符串


print("This is a test".replace('is','is_test'))       # This_test is_test a test

字典

clear方法清除字典中全部的項,這是一個原地操做,因此無返回值(或則說返回None)


d = {}
d['Tom']=8777
d['Jack']=9999
print(d)                               # {'Jack': 9999, 'Tom': 8777}
d.clear()
print(d)                               # {}

copy方法返回一個具備相同 」鍵-值」 對的新字典,而不是副本


d = {'Tom':8777,'Fly':6666}
a = d.copy()
a['Tom'] = '改變後的值'
print(d)                       #{'Fly': 6666, 'Tom': 8777}
print(a)                       #{'Fly': 6666, 'Tom': '改變後的值'}

# 查看內存地址
d={'tom':122,'fly':221}
id(d)
1932459885696

a=d.copy()
a
{'tom': 122, 'fly': 221}
id(a)
1932488640048

fromkeys方法使用給定的鍵創建新的字典,每一個鍵都對應一個默認的值None。

get方法是一個訪問字典項的方法

for循環字典的三種方法


d = {'Tom':8777,'Jack':8888,'Fly':6666}
for k,v in d.items():
  print(k,v)
for k in d.values():
  print(k)
for k in d.keys():
  print(k)

 


d = {'Tom':8777,'Jack':8888,'Fly':6666}
for k,v in d.items():
   print(k,v)
for k in d.values():
   print(k)
for k in d.keys():
   print(k)

pop方法 用於得到對應與給定鍵的值,而後將這個」鍵-值」對從字典中移除

update方法能夠利用一個字典項更新另外一個字典,提供的字典中的項會被添加到舊的字典中


>>> a
{'tom': 122, 'fly': 221}
>>> b={'age':20}
>>> a.update(b)
>>> a
{'tom': 122, 'fly': 221, 'age': 20}
將兩個列表組合成字典

keys = ['a', 'b']
values = [1, 2]

#一、zip生成字典
print(dict(zip(keys,values)))                       # {'a': 1, 'b': 2}
#二、for循環推倒字典
print({keys[i]: values[i] for i in range(len(keys))})       # {'a': 1, 'b': 2}

集合


list_1 = [1,2,3,4,5,1,2]
#一、去重(去除list_1中重複元素1,2)
list_1 = set(list_1)                                   #去重: {1, 2, 3, 4, 5}
print(list_1)
list_2 = set([4,5,6,7,8])

#二、交集(在list_1和list_2中都有的元素4,5)
print(list_1.intersection(list_2))                     #交集: {4, 5}

#三、並集(在list_1和list_2中的元素所有打印出來,重複元素僅打印一次)
print(list_1.union(list_2))                             #並集: {1, 2, 3, 4, 5, 6, 7, 8}

#四、差集
print(list_1.difference(list_2))                       #差集:在list_1中有在list_2中沒有:   {1, 2, 3}
print(list_2.difference(list_1))                       #差集:在list_1中有在list_2中沒有:   {8, 6, 7}

#五、子集
print(list_1.issubset(list_2))                         #子集:   False   List_1中的元素是否所有在list2中
#六、父集
print(list_1.issuperset(list_2))                       #父集:   False   List_1中是否包含list_2中的全部元素

#七、交集
print(list_1 & list_2)                                 #交集   {4, 5}

#八、union並集
print(list_1 | list_2)                                 #並集: {1, 2, 3, 4, 5, 6, 7, 8}

#九、difference差集
print(list_1 - list_2)                                 #差集:   {1, 2, 3}

#十、在集合中添加一個元素999
list_1.add(999)
print(list_1)                                           #Add()方法:         {1, 2, 3, 4, 5, 999}

#十一、刪除集合中任意一個元素不會打印刪除的值
list_1.pop()                                           #Pop()方法:     無返回值

#十二、discard刪除集合中的指定元素,如過沒有則返回None
print(list_1.discard("ddd"))                           #Discard()方法:   刪除指定的值,沒有返回None

 

字符編碼

  1. ASCII

    ASCII不支持中文字符

  2. GBK

    是中國的中文字符(中國人本身研發的),其包含了簡體中文和繁體中文的字符

  3. Unicode :  萬國編碼(Unicode 包含GBK)

    1. Unicode 是爲了解決傳統的字符編碼方案的侷限而產生的,它爲每種語言中的每一個字符設定了統一而且惟一的二進制編碼

    2. 規定雖有的字符和符號最少由 16 位來表示(2個字節),即:2 **16 = 65536

    3. 這裏還有個問題:使用的字節增長了,那麼形成的直接影響就是使用的空間就直接翻倍了

  4. Utf-8 : 可變長碼, 是Unicode 的擴展集

    1. UTF-8編碼:是對Unicode編碼的壓縮和優化,他再也不使用最少使用2個字節,而是將全部的字符和符號進行分類

    2. ASCII碼中的內容用1個字節保存、歐洲的字符用2個字節保存,東亞的字符用3個字節保存

python2和python3的區別

  1. 從編碼的角度來講

    python2 默認編碼方式ASCII碼(不能識別中文,要在文件頭部加上 #-- encoding:utf-8 -- 指定編碼方式)

    python3 默認編碼方式UTF-8(能識別中文,是Unicode 的擴展集)

    (可識別中文)

  2. 從輸出(print)的角度來講

    python2中加不加括號均可以打印

    python3中必須加括號

  3. 從輸入(input)的角度來講

    python2 raw_input()

    python3 input()

  4. 從range()函數的角度來講

    python2 range()/xrange()

    python3 range()

  5. 從類的角度來講

    python3 中都是新式類python2 中經典類和新式類混合

    新式類中使用廣度優先,經典類中使用深度優先

    python3 可使用superpython2 不能使用super

  6. 從字符串的角度來講

    python2中字符串有str和unicode兩種類型 

    python3 中字符串有str和字節(bytes) 兩種類型

  7. 從語法格式角度來講

    python3中再也不支持u中文的語法格式

    python2中支持

python2和python3中編碼轉換

  1. 在python3中字符串默認是unicode因此不須要decode(),直接encode(編碼)成想要轉換的編碼如gb2312

  2. 在python2中默認是ASCII編碼,必須先轉換成Unicode,Unicode 能夠做爲各類編碼的轉換的中轉站

深拷貝、淺拷貝

  • 深拷貝就是將一個對象拷貝到另外一個對象中,這意味着若是你對一個對象的拷貝作出改變時,不會影響原對象。在Python中,咱們使用函數deepcopy()執行深拷貝

  • 而淺拷貝則是將一個對象的引用拷貝到另外一個對象上,因此若是咱們在拷貝中改動,會影響到原對象。咱們使用函數copy()執行淺拷貝

  • 淺拷貝只是增長了一個指針指向一個存在的地址,

  • 而深拷貝是增長一個指針而且開闢了新的內存,這個增長的指針指向這個新的內存。

 

三元運算

  1. 三元運算格式: result=值1 if x<y else 值2 if條件成立result=1,不然result=2

  2. 做用:三元運算,又稱三目運算,主要做用是減小代碼量,是對簡單的條件語句的縮寫


#一個簡單的三元運算
a=name='小草' if1=1 else '小花'
print(a) # 小草

#三元運算 + lambda
f = lambda x:x if x % 2 != 0 else x + 100
print(f(10))                   # 110

 

IO多路複用

select、poll 、epoll(同步io)

不管是sellect、poll、epoll他們三個都是在I/O多路複用中檢測多個socket連接,與數據從內核態到數據態沒有什麼關係

https://www.cnblogs.com/xiaonq/p/7907871.html#i3

  • select,poll,epoll都是IO多路複用中的模型

    • 內核空間 操做系統才能訪問 操做系統 能夠調用cpu 掛起進程

      用戶空間 如qq 微信 運行在用戶空間

      IO多路複用(重點)

      特色: 用戶仍是要等待數據從內核拷貝到用戶進程

      Windows下只支持select

      Epoll有回調 會把數據加到鏈表中

      Select 無論你有沒數據 都放到鏈表中

      協程利用epoll greelit監聽請求

       

      協程又稱微線程,協程最主要的做用是在相似單線程的條件下實現併發的效果,但實際上仍是串行的(像yield同樣),爲何能處理併發,由於遇IO自動切換,協程內封裝Greenlet(遇到IO手動切換) 和Gevent(遇到IO自動切換),若是是耗時任務就會IO切換任務,會把任務交給操做系統,而後利用epoll,epoll有回調 會把數據加到鏈表中,告訴協程結果

      協程通常用於網絡請求 socket 連接

      請求自己是從內核copy到用戶空間

      select能監控數量有限(最大1024),不告訴用戶程序具體哪一個鏈接有數據

      poll和select同樣,僅僅去除了最大監控數量算是epoll過分

      epoll (不只沒有最大監控數量限制,還能告訴用戶程序哪一個鏈接有活躍(數據))一般使用epoll

      epoll() 中內核則維護一個鏈表,epoll_wait 直接檢查鏈表是否是空就知道是否有文件描述符準備好了

      在內核實現中 epoll 是根據每一個 sockfd 上面的與設備驅動程序創建起來的回調函數實現的。

  • 在高併發狀況下, 鏈接活躍度不是很高, epoll比select好

  • 在併發不高狀況下, 鏈接活躍度高, select比epoll好

進程(資源分配的單位)、線程(操做系統調度的最小單位)、協程


線程是指進程內的一個執行單元,
# 進程
進程擁有本身獨立的堆和棧,既不共享堆,亦不共享棧,進程由操做系統調度。
# 線程
線程擁有本身獨立的棧和共享的堆,共享堆,不共享棧,線程亦由操做系統調度
# 協程和線程
協程避免了無心義的調度,由此能夠提升性能;但同時協程也失去了線程使用多CPU的能力

進程與線程的區別
(1)地址空間:線程是進程內的一個執行單位,進程內至少有一個線程,他們共享進程的地址空間,而進程有本身獨立的地址空間
(2)資源擁有:進程是資源分配和擁有的單位,同一個進程內線程共享進程的資源
(3)線程是處理器調度的基本單位,但進程不是
(4)兩者都可併發執行
(5)每一個獨立的線程有一個程序運行的入口

協程與線程
(1)一個線程能夠有多個協程,一個進程也能夠單獨擁有多個協程,這樣Python中則能使用多核CPU
(2)線程進程都是同步機制,而協程是異步
(3)協程能保留上一次調用時的狀態

進程: 一個在運行起來的程序 系統給他分配資源 (運行在內存) 提資源

通訊的三種方式

​ 1 進程隊列queue

​ 2 管道pipe

​ 3 共享數據manage

進程說明

多個進程能夠在不一樣的 CPU 上運行,互不干擾

同一個CPU上,能夠運行多個進程,由操做系統來自動分配時間片

進程池

開多進程是爲了併發,一般有幾個cpu核心就開幾個進程,可是進程開多了會影響效率,主要體如今切換的開銷,因此引入進程池限制進程的數量。

進程池內部維護一個進程序列,當使用時,則去進程池中獲取一個進程,若是進程池序列中沒有可供使用的進進程,那麼程序就會等待,直到進程池中有可用進程爲止。

線程: 操做系統最小的調度單位,狀態保存在cpu的棧中

經常使用方法

join()方法

​ 實現全部線程都執行結束後再執行主線程

​ 若是一個線程或者在函數執行的過程當中調用另外一個線程,而且但願待其完成操做後才能執行, 那麼在 調用線程的時就可使用被調線程的join方法join([timeout]) timeout:可選參數,線程運行的最長時間

isAlive()方法

​ 查看線程是否還在運行

getName()方法

​ 得到線程名

setDaemon()方法

​ 主線程退出時,須要子線程隨主線程退出,則設置子線程的setDaemon()

線程鎖

線程鎖也叫用戶鎖 也叫互斥鎖、當前線程還未操做完成前其餘全部線程都沒法對其操做,即便已經釋放了GIL鎖

線程特性

線程,必須在一個存在的進程中啓動運行

線程使用進程得到的系統資源,不會像進程那樣須要申請CPU等資源

線程沒法給予公平執行時間,它能夠被其餘線程搶佔,而進程按照操做系統的設定分配執行時間

線程池

系統啓動一個新線程的成本是比較高的,由於它涉及與操做系統的交互。在這種情形下,使用線程池能夠很好地提高性能,尤爲是當程序中須要建立大量生存期很短暫的線程時,更應該考慮使用線程池。

線程池在系統啓動時即建立大量空閒的線程,程序只要將一個函數提交給線程池,線程池就會啓動一個空閒的線程來執行它。當該函數執行結束後,該線程並不會死亡,而是再次返回到線程池中變成空閒狀態,等待執行下一個函數。

 

協程: 微線程,纖程。 相似於單線程,不一樣於單線程,由於它能夠實現併發效果,由於有

gevent(封裝了c語言的greenlet) 遇io自動切換(greenlet能夠檢測io),把這個io請求交給epoll

greenlet框架封裝了yield語句、掛起函數,直到稍後使用next()或send()操做進行恢復爲止

猴子補丁

用過gevent就會知道,會在最開頭的地方gevent.monkey.patch_all();

做用是把標準庫中的thread/socket等給替換掉.無需修改任何代碼,把它變成了非阻塞

協程優勢:

​ 1.無需線程上下文切換的開銷 2.無需原子操做鎖定及同步的開銷 3.方便切換控制流,簡化編程模型 4.高併發+高擴展性+低成本:一個CPU支持上萬的協程都不是問題。因此很適合用於高併發處理。

缺點:

​ 1.沒法利用多核資源:協程的本質是個單線程,它不能同時將 單個CPU 的多個核用上,協程須要和進程配合才能 運行在多CPU上.固然咱們平常所編寫的絕大部分應用都沒有這個必要,除非是cpu密集型應

​ 2.線程阻塞(Blocking)操做(如IO時)會阻塞掉整個程序

  • 並行 :是多個程序運行在多個cpu上

  • 併發 :是一個時間段內,有幾個程序在同一個cpu上運行,可是任意時刻只有一個程序在cpu上運行

    通常多線程能夠稱爲併發 ,由於一個進程能夠有多個線程,強調的是一個進程

  • 詳細介紹 https://v3u.cn/book/p4.html 1.5

 

高階函數

1.map

通常狀況map()函數接收兩個參數,一個函數(該函數接收一個參數),一個序列,將傳入的函數依次做用到序列的每一個元素,並返回一個新的Iterator(迭代器)。 例若有這樣一個list:['pYthon', 'jaVa', 'kOtlin'],如今要把list中每一個元素首字母改成大寫,其它的改成小寫,能夠這樣操做:


>>> def f(s):
...   return s.title()
...
>>> l = map(f, ['pYthon', 'jaVa', 'kOtlin'])
>>> list(l)
['Python', 'Java', 'Kotlin']

2.reduce

和map()用法相似,reduce把傳入的函數做用在一個序列上,但傳入的函數須要接收兩個參數,傳入函數的計算結果繼續和序列的下一個元素作累積計算。

例若有一個list,裏邊的元素都是字符串,要把它拼接成一個字符串:


>>> from functools import reduce
>>> def f(x, y):
...   return x + y
...
>>> reduce(f, ['ab', 'c', 'de', 'f'])
'abcdef'

3.filter

filter()一樣接收一個函數和一個序列,而後把傳入的函數依次做用於序列的每一個元素,若是傳入的函數返回true則保留元素,不然丟棄,最終返回一個Iterator。

例如一個list中元素有純字母、純數字、字母數字組合的,咱們要保留純字母的:


>>> def f(s):
...   return s.isalpha()
...
>>> l = filter(f, ['abc', 'xyz', '123kg', '666'])
>>> list(l)
['abc', 'xyz']

4.sorted

sorted()函數就是用來排序的,同時能夠本身定義排序的規則。


>>> sorted([6, -2, 4, -1])
[-2, -1, 4, 6]

>>> sorted([6, -2, 4, -1], key=abs)
[-1, -2, 4, 6]

>>> sorted([6, -2, 4, -1], key=abs, reverse=True)
[6, 4, -2, -1]

>>> sorted(['Windows', 'iOS', 'Android'])
['Android', 'Windows', 'iOS']

>>> d = [('Tom', 170), ('Jim', 175), ('Andy', 168), ('Bob', 185)]
>>> def by_height(t):
...     return t[1]
...
>>> sorted(d, key=by_height)
[('Andy', 168), ('Tom', 170), ('Jim', 175), ('Bob', 185)]

5.lambda(匿名函數)

lambda只是一個表達式,函數體比def簡單不少。

lambda的主體是一個表達式,而不是一個代碼塊。僅僅能在lambda表達式中封裝有限的邏輯進去。

lambda表達式是起到一個函數速寫的做用。容許在代碼內嵌入一個函數的定義。

格式:lambda的通常形式是關鍵字lambda後面跟一個或多個參數,緊跟一個冒號,以後是一個表達式。


m=lambda i:i
lista=sorted([1,-2,3,-4,5,-6],key=abs)
print(lista)   #結果: [1, -2, 3, -4, 5, -6]


# 利用 filter、lambda表達式 獲取列表中元素小於33的全部元素
l1= [11,22,33,44,55]
a = filter(lambda x: x<33, l1)
print(list(a))

 

GIL全局解釋器鎖

一、什麼是GIL
  • GIL全稱Global Interpreter Lock,即全局解釋器鎖。 做用就是,限制多線程同時執行,保證同一時間內只有一個線程在執行。

  • GIL並非Python的特性,Python徹底能夠不依賴於GIL。

二、GIL的做用
  • 爲了更有效的利用多核處理器的性能,就出現了多線程的編程方式 ,同一個進程裏線程資源是共享的,當各個線程訪問數據資源時會出現競狀態 ,會出現數據混亂,解決多線程之間數據完整性和狀態同步最簡單的方式就是加鎖。GIL能限制多線程同時執行,保證同一時間內只有一個線程在執行。

三、GIL的影響
  • GIL無疑就是一把全局排他鎖。毫無疑問全局鎖的存在會對多線程的效率有不小影響。甚至就幾乎等於Python是個單線程的程序。

四、如何避免GIL的影響
  • 方法一:用進程+協程 代替 多線程的方式 在多進程中,因爲每一個進程都是獨立的存在,因此每一個進程內的線程都擁有獨立的GIL鎖,互不影響。可是,因爲進程之間是獨立的存在,因此進程間通訊就須要經過隊列的方式來實現。

  • 方法二 : 更換解釋器

    像JPython和IronPython這樣的解析器因爲實現語言的特性,他們不須要GIL的幫助。然而因爲用了Java/C#用於解析器實現,他們也失去了利用社區衆多C語言模塊有用特性的機會。因此這些解析器也所以一直都比較小衆。

5 爲何有時候加了GIL全局解釋器鎖 ,還要在加線程鎖?

由於cpu是分時分片的 ,若是GIL處理的任務特別繁瑣,到必定時間會自動切換其餘線程 形成混亂 ,因此要加一個線程鎖。

線程鎖

  • GIL(全局解釋器鎖)

    GIL並非Python的特性,它是在實現Python解析器(CPython)時所引入的一個概念,是爲了實現不一樣線程對共享資源訪問的互斥,才引入了GIL

    在Cpython解釋器中,同一個進程下開啓的多線程,同一時刻只能有一個線程執行,沒法利用多核優點

  • 互斥鎖(同步鎖)

    互斥鎖是用來解決上述的io密集型場景產生的計算錯誤,即目的是爲了保護共享的數據,同一時間只能有一個線程來修改共享的數據。

  • 死鎖

    保護不一樣的數據就應該加不一樣的鎖。因此當有多個互斥鎖存在的時候,可能會致使死鎖(有多是一個線程拿到鎖,並無釋放)

  • 遞歸鎖(重要)

    解決死鎖

  • Semaphore(信號量)

    實際上也是一種鎖,該鎖用於限制線程的併發量

裝飾器、迭代器、生成器

迭代器 含有iternext方法 (包含next方法的可迭代對象就是迭代器)

迭代器的定義:

 迭代器是訪問集合內元素的一種方式。迭代器對象從集合的第一個元素開始訪問,直到全部的元素都被訪問一遍後結束。 迭代器只能往前不會後退 。

可迭代對象

​ 可被for循環遍歷的對象都是可迭代的(Iterable)類型;

迭代器和可迭代對象關係:

​ 一個實現了iter方法的對象是可迭代的,一個實現next方法的對象是迭代器

迭代器僅是一容器對象,它實現了迭代器協議。它有兩個基本方法

     next方法

​      返回容器的下一個元素

     iter方法

​     返回迭代器自身

iter方法會返回一個迭代器(iterator),所謂的迭代器就是具備next方法的對象。
在調用next方法時,迭代器會返回它的下一個值,若是next方法被調用,但迭代器中沒有值能夠返就會引起一個StopIteration異常

 

生成器

包括含有yield這個關鍵字,生成器也是迭代器,調動next把函數變成迭代器

生成器工做原理

  • 生成器是這樣一個函數,它記住上一次返回時在函數體中的位置。

  • 對生成器函數的第二次(或第 n 次)調用跳轉至該函數中間,而上次調用的全部局部變量都保持不變。

yield運行機制

在Python中,yield就是一個生成器。 若是在函數內使用了yield關鍵字時,這個函數就是一個生成器

當你問生成器要一個數時,生成器會執行,直至出現 yield 語句,生成器把yield 的參數給你,以後生成器就不會往下繼續運行。

當你問他要下一個數時,他會從上次的狀態開始運行,直至出現yield語句,把參數給你,以後停下。如此反覆

每當調用一次迭代器的next函數,生成器函數運行到yield之處,返回yield後面的值且在這個地方暫停,全部的狀態都會被保持住,直到下次next函數被調用,或者碰到異常循環退出

手寫斐波那契


def fbnq(n):
  a,b=0,1
  while n>a:
      yield a
      a,b=b,a+b
if __name__ == '__main__':
  f=fbnq(9)
  print(next(f))   #打印結果 0
  print(next(f))   #打印結果 1

 

迭代器生成器區別

每次‘yield’暫停循環時,生成器會保存本地變量的狀態。而迭代器並不會使用局部變量,它只須要一個可迭代對象進行迭代。 使用類能夠實現你本身的迭代器,但沒法實現生成器。 生成器運行速度快,語法簡潔,更簡單。 迭代器更能節約內存。

 

裝飾器

裝飾器做用:本質是函數(裝飾其餘函數)就是爲其餘函數添加其餘功能

裝飾器必須準尋得原則
  • 不能修改被裝飾函數的源代碼

  • 不能修改被裝飾函數的調用方式

手寫三級裝飾器


import time
user,passwd = 'aaa','123'
def auth(auth_type):
  print("auth func:",auth_type)
  def outer_wrapper(func):
      def wrapper(*args, **kwargs):
          print("wrapper func args:", *args, **kwargs)
          if auth_type == "local":
              username = input("Username:").strip()
              password = input("Password:").strip()
              if user == username and passwd == password:
                  print("\033[32;1mUser has passed authentication\033[0m")
                  res = func(*args, **kwargs) # from home
                  print("---after authenticaion ")
                  return res
              else:
                  exit("\033[31;1mInvalid username or password\033[0m")
          elif auth_type == "ldap":
              print("搞毛線ldap,不會。。。。")

      return wrapper
  return outer_wrapper

def index():
  print("welcome to index page")
@auth(auth_type="local") # home = wrapper()
def home():
  print("welcome to home page")
  return "from home"

@auth(auth_type="ldap")
def bbs():
  print("welcome to bbs page")

index()
print(home()) #wrapper()
bbs()

 

裝飾器的應用場景

1,引入日誌2,函數執行時間統計3,執行函數前預備處理4,執行函數後清理功能5,權限校驗等場景6,緩存7,事務處理

閉包

在一個外函數中定義了一個內函數,內函數裏運用了外函數的臨時變量,而且外函數的返回值是內函數的引用,這樣就構成了一個閉包

可是閉包是一種特殊狀況,若是外函數在結束的時候發現有本身的臨時變量未來會在內部函數中用到,就把這個臨時變量綁定給了內部函數,而後本身再結束。

閉包特色

  1. 必須有一個內嵌函數

  2. 內嵌函數必須引用外部函數中的變量

  3. 外部函數的返回值必須是內嵌函數

os和sys模塊的做用?

OS模塊是Python標準庫中的一個用於訪問操做系統功能的模塊,使用OS模塊中提供的接口,能夠實現跨平臺訪問sys模塊主要是用於提供對python解釋器相關的操做

面向對象

面向對象方法

靜態方法

做用:靜態方法能夠更好的組織代碼,防止代碼變大後變得比較混亂。

特性: 靜態方法只是名義上歸類管理,實際上在靜態方法裏訪問不了類或則實例中的任何屬性

靜態方法使用場景:    常常有一些跟類有關係的功能但在運行時又不須要實例和類參與的狀況下 須要用到靜態方法.     好比更改環境變量或者修改其餘類的屬性等能用到靜態方法.     這種狀況能夠直接用函數解決, 但這樣一樣會擴散類內部的代碼,形成維護困難.

調用方式: 既能夠被類直接調用,也能夠經過實例調用


class Dog(object):
  def __init__(self,name):
      self.name = name
  @staticmethod
  def eat():
      print("I am a static method")
d = Dog("ChenRonghua")
d.eat()                       #方法1:使用實例調用
Dog.eat()                   #方法2:使用類直接調用

類方法

做用:無需實例化直接被類調用

特性: 類方法只能訪問類變量,不能訪問實例變量

類方法使用場景: 當咱們還未建立實例,可是須要調用類中的方法

調用方式: 既能夠被類直接調用,也能夠經過實例調用


class Dog(object):
  name = '類變量' #在這裏若是不定義類變量僅定義實例變量依然報錯
  def __init__(self,name):
      self.name = '實例變量'
      self.name = name
  @classmethod
  def eat(self,food):
      print("%s is eating %s"%(self.name,food))
Dog.eat('baozi')                   #方法1:使用類直接調用
d = Dog("ChenRonghua")          
d.eat("包子")                     #方法2:使用實例d調用

屬性方法

做用:屬性方法把一個方法變成一個屬性,隱藏了實現細節,調用時沒必要加括號直接d.eat便可調用self.eat()方法


class Dog(object):
  def __init__(self, name):
      self.name = name

  @property
  def eat(self):
      print(" %s is eating" % self.name)
d = Dog("ChenRonghua")
d.eat()
# 調用會出如下錯誤, 說NoneType is not callable, 由於eat此時已經變成一個靜態屬性了,
# 不是方法了, 想調用已經不須要加()號了,直接d.eat就能夠了

特殊(魔術)方法

__ doc __  表示類的描述信息

__ call __ 對象後面加括號,觸發執行

__ str __ 若是一個類中定義了__ str __方法,在打印對象時,默認輸出該方法的返回值

__ dict __ 查看類或對象中的全部成員

newinit的區別

    一、 new是一個靜態方法,而init是一個實例方法.    二、 new方法會返回一個建立的實例,而init什麼都不返回.    三、 只有在new返回一個cls的實例時後面的init才能被調用.    四、 當建立一個新實例時調用new,初始化一個實例時用init.

單例模式

一、單例模式:永遠用一個對象得實例,避免新建太多實例浪費資源二、實質:使用new方法新建類對象時先判斷是否已經創建過,若是建過就使用已有的對象三、使用場景:若是每一個對象內部封裝的值都相同就能夠用單例模式


class Foo(object):
  instance = None
  def __init__(self):
    self.name = 'alex'

  def __new__(cls, *args, **kwargs):
    if Foo.instance:
        return Foo.instance
    else:
        Foo.instance = object.__new__(cls,*args,**kwargs)
        return Foo.instance

obj1 = Foo()       # obj1和obj2獲取的就是__new__方法返回的內容
obj2 = Foo()
print(obj1,obj2)  
# 運行結果: <__main__.Foo object at 0x00D3B450>   <__main__.Foo object at 0x00D3B450>

# 運行結果說明:
# 這能夠看到咱們新建的兩個Foo()對象內存地址相同,說明使用的•同一個類,沒有重複創建類

面向對象屬性

class Role(object):                    #一、在定義類時繼承object就是新式類,沒有就是就是舊類式
    public_object = "public"           #二、在類例定義一個公有屬性:全部實例都能訪問的屬性叫「公有屬性」
    def __init__(self,name,role,weapon,life_value=100,money=15000):  #構造函數==初始化方法:模板
        self.name = name               #三、普通屬性
        self.__heart= "Normal"        #四、私有屬性在外面沒法訪問,在名字前加__(雙下劃線) 外部沒法訪問
    def shot(self):                    #五、類的方法
        print("%s is shooting..."%self.name)


公有屬性

公有屬性:在內存中僅存一份

普通屬性

普通屬性:每一個實例對象在內存存一份

私有屬性

私有屬性:實例在外部沒法調用

 

反射

  • 反射的核心本質就是以字符串的形式去導入個模塊,利用字符串的形式去執行函數。

    Django中的 CBV就是基於反射實現的。

     

新式類和經典類的區別

​ ❶經典類 沒有繼承object , 新式類 繼承了object

​ ❷多繼承中,新式類採用廣度優先搜索,而舊式類是採用深度優先搜索,python3中全是廣度查詢

​ ❸在繼承中新式類和經典類寫法區別

	SchoolMember.__init__(self,name,age,sex)                      #經典類寫法
	super(Teacher,self).__init__(name,age,sex)                    #新式類寫法


 

面向對象深度優先和廣度優先是什麼?

一、區別

  • 1) 二叉樹的深度優先遍歷的非遞歸的通用作法是採用棧,廣度優先遍歷的非遞歸的通用作法是採用隊列。

  • 2) 深度優先遍歷:對每個可能的分支路徑深刻到不能再深刻爲止,並且每一個結點只能訪問一次。要特別注意的是,二叉樹的深度優先遍歷比較特殊,能夠細分爲先序遍歷、中序遍歷、後序遍歷。具體說明以下:

  • 廣度優先遍歷:又叫層次遍歷,從上往下對每一層依次訪問,在每一層中,從左往右(也能夠從右往左)訪問結點,訪問完一層就進入下一層,直到沒有結點能夠訪問爲止。 

三大特性:封裝,繼承,多態

Encapsulation 封裝(隱藏實現細節)

在面向對象思想中,對一個類,將數據和過程封包圍起來,對外隱藏具體的實現細節  而且數據(成員變量和成員函數)在內部是徹底自由使用的,而外部對數據的訪問是加訪問限定的,某些對操做只能根據由內部提供接口。

Inheritance 繼承(代碼重用)

​ 繼承能夠說是一種代碼複用的手段,咱們在一個現有類上想擴展出一些東西的時候,不須要再次重複編寫上面的代碼,而是採用一種繼承的思想。在派生出的子類裏添加一些咱們想要的數據或方法,也能夠理解爲從通常到特殊的過程。

Polymorphism 多態(接口重用)

這裏先說運行時多態,實際上是指在繼承體系中父類的一個接口(必須爲虛函數),在子類中有多種不一樣的實現,父對象就能夠根據當前賦值給它的子對象的特性以不一樣的方式運做。即經過父類指針或者引用能夠訪問到子類的接口(虛函數),看上去就像是一個相同的動做,會出現多種不一樣的結果。

 

垃圾回收機制

1.引用計數

原理

  • 當一個對象的引用被建立或者複製時,對象的引用計數加1;當一個對象的引用被銷燬時,對象的引用計數減1

  • 當對象的引用計數減小爲0時,就意味着對象已經再沒有被使用了,能夠將其內存釋放掉。

優勢

  • 引用計數有一個很大的優勢,即實時性,任何內存,一旦沒有指向它的引用,就會被當即回收,而其餘的垃圾收集技術必須在某種特殊條件下才能進行無效內存的回收。

缺點

  • 引用計數機制所帶來的維護引用計數的額外操做與Python運行中所進行的內存分配和釋放,引用賦值的次數是成正比的,

  • 這顯然比其它那些垃圾收集技術所帶來的額外操做只是與待回收的內存數量有關的效率要低。

  • 同時,由於對象之間相互引用,每一個對象的引用都不會爲0,因此這些對象所佔用的內存始終都不會被釋放掉。

爲了解決以上問題:

2.標記-清除

  • 標記-清除: 只關注那些可能會產生循環引用的對象,

  • 把全部能夠訪問到的對象打上標記,而後清掃一遍內存空間,把全部沒標記的對象釋放

 缺點:標記和清除的過程效率不高

原理

  • 基本思路是先按需分配,等到沒有空閒內存的時候從寄存器和程序棧上的引用出發,遍歷以對象爲節點

  • 以引用爲邊構成的圖,把全部能夠訪問到的對象打上標記,而後清掃一遍內存空間,把全部沒標記的對象釋放

3.分代回收

  • 將系統中的全部內存塊根據其存活時間劃分爲不一樣的集合,每個集合就成爲一個「代」,垃圾收集的頻率隨着「代」的存活時間的增大而減少。

  • 也就是說,活得越長的對象,就越不多是垃圾,就應該減小對它的垃圾收集頻率。

  • 那麼如何來衡量這個存活時間:一般是利用幾回垃圾收集動做來衡量,若是一個對象通過的垃圾收集次數越多,能夠得出:該對象存活時間就越長。

 

三種讀文件方式

1.readline()

readline()每次讀取一行,當前位置移到下一行readline()做用:readline 的用法,速度是fileinput的3倍左右,每秒3-4萬行,好處是 一行行讀 ,不佔內存,適合處理比較大的文件,好比超過內存大小的文件

#readline讀取大文件#
f1 = open('test02.py','r')
f2 = open('test.txt','w')
while True:
    line = f1.readline()
    if not line:
        break
    f2.write(line)
f1.close()
f2.close()


 

2.readlines()

readlines()讀取整個文件全部行,保存在一個列表(list)變量中,每行做爲一個元素readlines()做用:readlines會把文件都讀入內存,速度大大增長,可是沒有這麼大內存,那就只能乖乖的用readline

#readlines讀文件#
f1=open("readline.txt","r")
for line in f1.readlines():
    print(line)


 

3.read(size)

read(size)從文件當前位置起讀取size個字節,若是不加size會默認一次性讀取整個文件(適用於讀取小文件)read(n)讀取指定長度的文件

f = open(r"somefile.txt")
print(f.read(7))        # Welcome        先讀出 7 個字符
print(f.read(4))        #‘ to ‘                接着上次讀出 4 個字符
f.close()
 seek(offset[, whence])  隨機訪問 :從文件指定位置讀取或寫入 

f = open(r"somefile.txt", "w")
f.write("01234567890123456789")
f.seek(5)
f.write("Hello, World!")
f.close()
f = open(r"somefile.txt")
print(f.read())                 # 01234Hello, World!89
tell 返回當前讀取到文件的位置下標 


 

tcp udp

tcp

三次握手

####一、第一次握手
# 創建鏈接時,客戶端發送SYN包到服務器,其中包含客戶端的初始序號seq=x,並進入SYN_SENT狀態,等待服務器確認。

####二、第二次握手
# 服務器收到請求後,必須確認客戶的數據包。同時本身也發送一個SYN包,即SYN+ACK包,此時服務器進入SYN_RECV狀態。

####三、第三次握手
# 客戶端收到服務器的SYN+ACK包,向服務器發送一個序列號(seq=x+1),確認號爲ack(客戶端)=y+1,此包發送完畢,
# 客戶端和服務器進入ESTAB_LISHED(TCP鏈接成功)狀態,完成三次握手。


四次揮手

#### 一、第一次揮手
# 首先,客戶端發送一個FIN,用來關閉客戶端到服務器的數據傳送,而後等待服務器的確認。其中終止標誌位FIN=1,序列號seq=u。

#### 二、第二次揮手
# 服務器收到這個FIN,它發送一個ACK,確認ack爲收到的序號加一。

#### 三、第三次揮手
# 關閉服務器到客戶端的鏈接,發送一個FIN給客戶端。

#### 四、第四次揮手
# 客戶端收到FIN後,併發回一個ACK報文確認,並將確認序號seq設置爲收到序號加一。
# 首先進行關閉的一方將執行主動關閉,而另外一方執行被動關閉。


TCP與UDP比較

  1. TCP面向鏈接(如打電話要先撥號創建鏈接);UDP是無鏈接的,即發送數據以前不須要創建鏈接

  2. TCP提供可靠的服務,也就是說,經過TCP鏈接傳送的數據,無差錯,不丟失,不重複,且按序到達; UDP盡最大努力交付,即不保證可靠交付

  3. Tcp經過校驗和,重傳控制,序號標識,滑動窗口、確認應答實現可靠傳輸。

  4. UDP具備較好的實時性,工做效率比TCP高,適用於對高速傳輸和實時性有較高的通訊或廣播通訊。

  5. 每一條TCP鏈接只能是點到點的;UDP支持一對一,一對多,多對一和多對多的交互通訊

  6. TCP對系統資源要求較多,UDP對系統資源要求較少。

    注:UDP通常用於即時通訊(QQ聊天 對數據準確性和丟包要求比較低,但速度必須快),在線視頻等

 

tcp/udp相關協議

  1. TCP: STMP, TELNET, HTTP, FTP

    2.UDP: DNS,TFTP,RIP,DHCP,SNMP

 

Websocket

​ 1.是一種在單個TCP鏈接上進行 全雙工通訊(又稱爲雙向同時通訊,即通訊的雙方能夠同時發送和接收信 息的信息交互方式。)的協議。

​ 2.WebSocket使得客戶端和服務器之間的數據交換變得更加簡單,容許服務端主動向客戶端推送數據。在WebSocket API中,瀏覽器和服務器只須要完成一次握手,二者之間就直接能夠建立持久性的鏈接,並進行雙向數據傳輸。

 

數據結構

棧的定義

棧是一種數據集合,能夠理解爲只能在一端進行插入或刪除操做的列表

棧的特色

後進先出 棧有棧頂和棧底

棧的基本操做

進棧(壓棧):push

出棧:pop

取棧頂:gettop

棧的應用場景

匹配括號是否成對出現

def check_kuohao(s):
   stack = []
   for char in s:
      if char in ['(','[','{']:
         stack.append(char)
      elif char == ')':
         if len(stack)>0 and stack[-1] == '(':
            stack.pop()
         else:
            return False
      elif char == ']':
         if len(stack) > 0 and stack[-1] == '[':
            stack.pop()
         else:
            return False
      elif char == '}':
         if len(stack) > 0 and stack[-1] == '{':
            stack.pop()
         else:
            return False
   if len(stack) == 0:
      return True
   else:
      return False
print(check_kuohao('(){}{}[]'))  #True


隊列

隊列的定義

  1. 隊列是一個數據集合,僅容許在列表的一端進行插入,另外一端進行刪除

  2. 插入的一端稱爲隊尾(rear),插入動做叫進隊或入隊

  3. 進行刪除的一端稱爲對頭(front),刪除動做稱爲出隊

  4. 隊列性質:先進先出(First-in, First-out)

  5. 雙向隊列:隊列的兩端都容許進行進隊和出隊操做

隊列的使用方法

  1. 導入: from collectios import deque

  2. 建立隊列:queue = deque(li)

  3. 進隊: append

  4. 出隊: popleft

  5. 雙向隊列隊首進隊:appendleft

  6. 雙向隊列隊尾出隊:pop

鏈表

單鏈表

鏈表中每一個元素都是一個對象,每一個對象稱爲一個節點,包含有數據域key和指向下一節點的指針next,經過各個節點間的相互鏈接,最終串聯成一個鏈表

單鏈表第一個節點沒有前驅,最後一個節點沒有後繼。

鏈表反轉
class Node(object):
    def __init__(self, val):
        self.val = val
        self.next = None

def list_reverse(head):
    if head == None:
        return None
    L, R, cur = None, None, head  # 左指針、有指針、遊標
    while cur.next != None:
        L = R             # 左側指針指向之前右側指針位置
        R = cur           # 右側指針前進一位指向當前遊標位置
        cur = cur.next    # 遊標每次向前進一位
        R.next = L        # 右側指針指向左側實現反轉
    cur.next = R          # 當跳出 while 循環時 cur(原鏈表最後一個元素) R(原鏈表倒數第二個元素)
    return cur

if __name__ == '__main__':
    '''
    原始鏈表:1 -> 2 -> 3 -> 4
    反轉鏈表:4 -> 3 -> 2 -> 1
    '''
    l1 = Node(1)
    l1.next = Node(2)
    l1.next.next = Node(3)
    l1.next.next.next = Node(4)
    l = list_reverse(l1)
    print l.val         # 4  反轉後鏈表第一個值4
    print l.next.val    # 3  第二個值3


雙鏈表

雙鏈表中每一個節點有兩個指針:一個指針指向後面節點、一個指向前面節點

單向循環鏈表

本質和單向聯鏈表同樣,但循環鏈表的最後一個結點的指針是指向該循環鏈表的第一個結點或者表頭結點,從而構成一個環形的鏈。

 

數組

數組的定義

  1. 所謂數組,就是相同數據類型的元素按必定順序排列的集合

  2. 在Java等其餘語言中並非全部的數據都能存儲到數組中,只有相同類型的數據才能夠一塊兒存儲到數組中。

  3. 由於數組在存儲數據時是按順序存儲的,存儲數據的內存也是連續的,因此他的特色就是尋址讀取數據比較容易,插入和刪除比較困難。

python中list與數組比較
  1. python中的list是python的內置數據類型,list中的數據類沒必要相同的,而array的中的類型必須所有相同。

  2. 在list中的數據類型保存的是數據的存放的地址,簡單的說就是指針,並不是數據

  3. 這樣保存一個list就太麻煩了,例如list1=[1,2,3,'a']須要4個指針和四個數據,增長了存儲和消耗cpu。

 

字典實現原理

哈希表
  1. 哈希表(也叫散列表),根據關鍵值對(Key-value)而直接進行訪問的數據結構。

    它經過把key和value映射到表中一個位置來訪問記錄,這種查詢速度很是快,更新也快。

  2. 而這個映射函數叫作哈希函數,存放值的數組叫作哈希表

 

Python經常使用模塊

http://www.javashuo.com/article/p-qqhiwvjk-r.html

subprocess

subprocess原理
  1. 運行python的時候,咱們都是在建立並運行一個進程。像Linux進程那樣,一個進程能夠fork一個子進程,並讓這個子進程exec另一個程序

  2. 在Python中,咱們經過標準庫中的subprocess包來fork一個子進程,並運行一個外部的程序。

  3. subprocess包中定義有數個建立子進程的函數,這些函數分別以不一樣的方式建立子進程,因此咱們能夠根據須要來從中選取一個使用

  4. 另外subprocess還提供了一些管理標準流(standard stream)和管道(pipe)的工具,從而在進程間使用文本通訊。

 

subprocess.Popen()

​ Popen對象建立後,主程序不會自動等待子進程完成。咱們必須調用對象的wait()方法,父進程纔會等待 (也就是阻塞block)

subprocess.PIPE

將多個子進程的輸入和輸出鏈接在一塊兒

subprocess.PIPE實際上爲文本流提供一個緩存區。child1的stdout將文本輸出到緩存區,隨後child2的stdin從該PIPE中將文本讀取走

paramiko

Paramiko模塊做用
  1. 若是須要使用SSH從一個平臺鏈接到另一個平臺,進行一系列的操做時,

​ 好比:批量執行命令,批量上傳文件等操做,paramiko是最佳工具之一。

  1. paramiko是用python語言寫的一個模塊,遵循SSH2協議,支持以加密和認證的方式,進行遠程服務器的鏈接

  2. 支持多平臺 如Linux, Solaris, BSD,MacOS X, Windows等

re

經常使用正則表達式符號

通配符 ●

      做用:● 能夠匹配除換行符之外的任意一個字符串

轉義字符 ╲

      做用:能夠將其餘有特殊意義的字符串以本來意思表示

      注:若是想對反斜線(\)自身轉義可使用雙反斜線(\\)這樣就表示’\’

字符集

      做用:使用中括號來括住字符串來建立字符集,字符集可匹配他包括的任意字串

        ‘[pj]ython’ 只可以匹配‘python’ ‘jython’

         [a-z] 可以(按字母順序)匹配a-z任意一個字符

         [a-zA-Z0-9] 能匹配任意一個大小寫字母和數字

         ^abc 能夠匹配任意除a,b和c 以外的字符串

管道符

      做用:一次性匹配多個字符串

      例如:’python|perl’ 能夠匹配字符串‘python’ 和 ‘perl’

 

.最經常使用的匹配方法

       \d 匹配任何十進制數;它至關於類 [0-9]。       \D 匹配任何非數字字符;它至關於類 0-9       \s 匹配任何空白字符;它至關於類 [ fv]。       \S 匹配任何非空白字符;它至關於類 fv       \w 匹配任何字母數字字符;它至關於類 [a-zA-Z0-9_]。       \W 匹配任何非字母數字字符;它至關於類 a-zA-Z0-9_

       \w* 匹配全部字母字符

       \w+ 至少匹配一個字符

匹配時忽略大小寫

import re
#匹配時忽略大小寫
print(re.search("[a-z]+","abcdA").group())                #abcd
print(re.search("[a-z]+","abcdA",flags=re.I).group())     #abcdA

sys

sys基本方法

    sys.argv          返回執行腳本傳入的參數

    sys.exit(n)      退出程序,正常退出時exit(0)

    sys.version    獲取Python解釋程序的版本信息

    sys.maxint    最大的Int值

    sys.path    返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值

    sys.platform    返回操做系統平臺名稱

os

import os
# 當前工做目錄,即當前python腳本工做的目錄路徑
print(os.getcwd())    # C:\Users\admin\PycharmProjects\s14\Day5\test4

# 當前腳本工做目錄;至關於shell下cd
os.chdir("C:\\Users\\admin\\PycharmProjects\\s14")
os.chdir(r"C:\Users\admin\PycharmProjects\s14")
print(os.getcwd())    # C:\Users\admin\PycharmProjects\s14

# 返回當前目錄: ('.')
print(os.curdir)        # ('.')

#4 獲取當前目錄的父目錄字符串名:('..')
print(os.pardir)        # ('..')

# 可生成多層遞歸目錄
os.makedirs(r'C:\aaa\bbb')         # 能夠發如今C盤建立了文件夾/aaa/bbb

# 若目錄爲空,則刪除,並遞歸到上一級目錄,如若也爲空,則刪除,依此類推
os.removedirs(r'C:\aaa\bbb')    # 刪除全部空目錄


# 刪除單級空目錄,若目錄不爲空則沒法刪除,報錯;至關於shell中rmdir dirname
os.rmdir(r'C:\aaa')        # 僅刪除指定的一個空目錄

# 列出指定目錄下的全部文件和子目錄,包括隱藏文件,並以列表方式打印
print(os.listdir(r"C:\Users\admin\PycharmProjects\s14"))

# 刪除一個文件
os.remove(r'C:\bbb\test.txt')        # 指定刪除test.txt文件

# 重命名文件/目錄
os.rename(r'C:\bbb\test.txt',r'C:\bbb\test00.bak')

# 獲取文件/目錄信息
print(os.stat(r'C:\bbb\test.txt'))

# 運行shell命令,直接顯示
os.system("bash command")

# 獲取系統環境變量
print(os.environ)                # environ({'OS': 'Windows_NT', 'PUBLIC': ………….

# 返回path規範化的絕對路徑
print(os.path.abspath(r'C:/bbb/test.txt'))    # C:\bbb\test.txt

# 將path分割成目錄和文件名二元組返回
print(os.path.split(r'C:/bbb/ccc'))    # ('C:/bbb', 'ccc')

# 不管linux仍是windows,拼接出文件路徑
put_filename = '%s%s%s'%(self.home,os. path.sep, filename)
#C:\Users\admin\PycharmProjects\s14\day10select版FTP\home


time

time()模塊中的重要函數**
函數 描述
asctime([tuple]) 將時間元組轉換爲字符串
localtime([secs]) 將秒數轉換爲日期元組(轉換成本國時區
mktime(tuple) 將時間元組轉換爲本地時間
time() 獲取當前時間戳
   
time()模塊時間轉換**
  1. 時間戳 1970年1月1日以後的秒, 即:time.time()

  2. 格式化的字符串 2014-11-11 11:11, 即:time.strftime('%Y-%m-%d')

  3. 結構化時間 元組包含了:年、日、星期等... time.struct_time 即:time.localtime()

datetime


import datetime
#一、datetime.datetime獲取當前時間
print(datetime.datetime.now())
#二、獲取三天後的時間
print(datetime.datetime.now()+datetime.timedelta(+3))
#三、獲取三天前的時間
print(datetime.datetime.now()+datetime.timedelta(-3))
#四、獲取三個小時後的時間
print(datetime.datetime.now()+datetime.timedelta(hours=3))
#五、獲取三分鐘之前的時間
print(datetime.datetime.now()+datetime.timedelta(minutes = -3))

import datetime
print(datetime.datetime.now())                                   #2017-08-18 11:25:52.618873
print(datetime.datetime.now().date())                            #2017-08-18
print(datetime.datetime.now().strftime("%Y-%m-%d %H-%M-%S"))    #2017-08-18 11-25-52

時間戳轉換成datetime對象
# datetime.datetime.fromtimestamp(1520561646.8906238)
datetime.datetime(2018, 3, 9, 10, 14, 6, 890624)
相關文章
相關標籤/搜索