Python是一門解釋型的、動態型的OOP語言,結識Python的這幾年來,其語法的簡潔、結構的條理性深入的吸引了我。下面是我總結出來的一些Python經常使用知識點。html
需求: 將[[1,2],[3,4]] 轉換爲[1,2,3,4],具體實現有如下幾種方法python
test_list = [[1,2],[3,4]]
1. from itertools import chain
list(chain.from_iterable(test_list))
結果:[1, 2, 3, 4]
2. from itertools import chain
list(chain(*test_list))
結果:[1, 2, 3, 4]
3. sum(test_list, [])
結果:[1, 2, 3, 4]
4. [x for y in test_list for x in y]
結果:[1, 2, 3, 4]
5. 萬能方法(遞歸)
func = lambda x: [y for t in x for y in func(t)] if type(x) is list else [x]
func(test_list)
結果:[1, 2, 3, 4]複製代碼
PS: 項目中,不免會有相似的需求,對於結構嵌套一致的狀況,上述的1,2,3,4方法均可以很好的解決(不建議用for循環嵌套的方式,那是最low的方法,沒有之一);對於結構嵌套不一致的狀況,第5種方法就派上了用場,其採用了遞歸的思想,堪稱萬能的方法,屢試不爽。項目中,你們能夠根據實際應用場景來挑選最適合本身的方法。肚中有糧,心中不慌;你們能夠把上述方法都記下來,以作到有的放矢。web
對於Python的三元表達式,想必你們對if else
都不會感到陌生,可是對and or
操做想必是另外一種感受了,不過你們對其餘語言的? :
應該不會陌生,沒錯,此次的主角and or
就和? :
有着殊途同歸之妙。ajax
代碼參考:django
1 == 1 and 2 or 3 返回2
1 == 2 and 2 or 3 返回3複製代碼
PS:習慣於if else
的同窗偶爾用下and or
是否是會給人耳目一新的感受。json
1 and 2 and 3 返回3
1 and 2 and '' 返回''
'' and 2 and 0 返回''
PS:若是都爲真則返回最後一個值,若是其中某些值爲假,則返回第一個爲假的值複製代碼
1 or '' or 0 返回1
'' or 0 or [] 返回[]
PS:若是都爲假返回最後一個值,若是其中某些值爲真,則返回第一個爲真的值複製代碼
使用場景:在項目中咱們常常會有這樣的需求,在將一個字典更新以後還想要返回更新後的字典,這是咱們就能夠這樣寫:dic = dic1.update(dic2) or dic1
緩存
需求:將[1,2,3]中的每一項都加1bash
good: [x+1 for x in [1,2,3]]
bad: def add_list(goal_list):
tmp_list = []
for x in goal_list:
tmp_list.append(x+1)複製代碼
PS: 列表推導式底層是用C實現的,其執行速度要比for循環快好多服務器
代碼參考:app
```
def func(a, b, c):
print vars()
執行func(1, 2, 3)
輸出:{"a":1,"b":2,"c":3}
PS: vars()的值爲字典,其鍵值對來源於當前做用域的全部變量。
```複製代碼
使用場景:在調用他人接口或方法時,須要將傳入的參數打印以記錄日誌,此刻vars()便派上用場了。
代碼示例:
import functools
def add(a, b):
return a + b
add(4, 2)
6
plus3 = functools.partial(add, 3)
plus5 = functools.partial(add, 5)
plus3(4)
7
plus3(7)
10
plus5(10)
15複製代碼
實際使用心得:
以前作對象存儲的項目中,我須要同時去調用三個同樣的接口(大部分參數同樣)下面是個人部分代碼,供你們參考
my_thread = functools.partial(myThread, dic, zone_id, start, end, customer_id) my_thread1 = my_thread("day", "gets", "2") my_thread1 = my_thread("day", "original_traffic", "3")複製代碼
使用場景:
當咱們須要同時去調用一個函數,而且發現大部分參數一致的時候,即可以採起上述方法,一來代碼簡潔,二來可讀性高。
python -m smtpd -n -c DebuggingServer localhost:1025
Python搭建簡易web服務器:
python -m SimpleHTTPServer port
python -m http.server port
Python搭建簡易ftp服務
pip install pyftpdlib
python -m pyftpdlib -p 21
ftp://localhost:21複製代碼
在項目中遍歷字典是很常見的需求,下面介紹下經常使用的方法並作下比較:
dic = {'name': 'peter', 'age': 27}
1. for key, value in dic.items():
print key, value
2. for key, value in dic.iteritems():
print key, value複製代碼
PS:iteritems
和items
的區別在於iteritems
採用了生成器的原理,只有在須要的時候纔會把值生成,其之間的區別相似於range
和 xrange
;readline
和 xreadline
Python的內存管理主要分爲引用計數和垃圾回收機制兩大部分,且看下面代碼:
[ ] 內存分配:
a = 1
b = 1
a is b True
---------------------
a = 1000
b = 1000
a is b False複製代碼
PS: 在Python中,整數和短小的字符,Python都會緩存這些對象,以便重複使用。當咱們建立多個等於1的引用時,其實是讓這些引用指向了同一個對象。
[ ] 引用計數:
在Python中,所謂引用計數(reference count)是指全部指向該對象的引用的總數;
咱們可使用sys
包中的getrefcount()
,來查看某個對象的引用計數。須要注意的是,當使用該函數查看某個對象的引用計數時,其實是臨時建立了該對象的一個新的引用,全部使用getrefcount()
所獲得的結果,會比指望的值多1。
from sys import getrefcount
aa = 'test refcount'
print(getrefcount(a))
bb = aa
print(getrefcount(a))複製代碼
PS: 因爲上述緣由,兩個getrefcount()
將返回2和3,並非指望的1和2.
[ ] 引用減小
引用減小大體分爲兩類:
指向該對象的引用指向了其餘對象
from sys import getrefcount
aa = 'test refcount'
bb = aa
print(getrefcount(aa)) 3
bb = 1
print(getrefcount(aa)) 2複製代碼
使用del
關鍵字顯示的刪除某個引用
from sys import getrefcount
aa = 'test refcount'
bb = aa
print(getrefcount(aa)) 3
del bb
print(getrefcount(aa)) 2複製代碼
[ ] 垃圾回收
不斷的建立對象,若是不及時銷燬的話,那Python的體積會愈來愈大,再大的內存也會有耗完的時候;不用像C語言那樣,須要手動的去管理內存、Python已經幫咱們作好了(Python的垃圾回收機制),你只須要去關心你的業務邏輯便可,其餘的都交給Python來處理。
從原理上講,當Python中某個對象的引用計數降爲0時,該對象就應該被回收。可是頻繁的啓動垃圾回收機制畢竟是個很耗時的問題;所以Python只有在特定條件下(當Python中被分配對象和取消分配對象的次數之間的差值達到某個閾值時),Python會自動啓動垃圾回收機制。
咱們能夠經過gc
模塊的get_threshold()
方法,查看該閾值:
import gc
print(gc.get_threshold())複製代碼
該方法會返回(700, 10, 10)
,後面的倆10是與分代回收相關的,稍後講解。700即是垃圾回收機制啓動的閾值。能夠經過gc
模塊中的set_threshold()
方法從新設定該值。
固然了,咱們也能夠手動啓動垃圾回收機制,使用gc.collect()
便可。
[ ] 分代回收
Python同時採用了分代回收的機制,設想一下:存活越久的對象、越不多是垃圾對象。程序在運行時,每每會產生大量的臨時對象,程序結束以後,這些臨時對象的生命週期也就隨之告一段落。但有一些對象會被長期佔用,垃圾回收機制在啓動的時候會減小掃描到他們的頻率。
Python將全部對象分爲0,1,2三代。全部新建立的對象都是0代,當垃圾回收機制在啓動屢次0代機制並掃描到他們的時候,這些對象若是依然存活在內存的話,他們就會被納入下一代對象,以此類推。
剛纔上面所提到的(700, 10, 10)
三個參數後面的倆10所表明的意思是:每10次0代垃圾回收,會配合1次1代的垃圾回收;而每10次1代的垃圾回收會配合1次的2代垃圾回收。
固然咱們一樣可使用set_threshold()
來調整此策略的比例,好比對1代對象進行更頻繁的掃描。
import gc
gc.set_threshold(700, 5, 10)複製代碼
[ ] 新式類: 顯示的繼承了object
的類
class A(object):
attr = 1
class B(A):
pass
class C(A):
attr = 3
class D(B, C):
pass
if __name__ == '__main__':
d = D()
print 'attr = ', d.attr # attr = 3複製代碼
[ ] 經典類:沒有繼承自object
的類
class A():
attr = 1
class B(A):
pass
class C(A):
attr = 3
class D(B, C):
pass
if __name__ == '__main__':
d = D()
print 'attr = ', d.attr # attr = 1複製代碼
PS: 經過以上代碼的輸出結果能夠看出,新式類會廣度搜索,也就是一層層的向上搜索;經典類是深度優先,即遇到一個超類點就向上搜索。
Python的裝飾器被稱爲Python的語法糖,哪裏須要粘哪裏。
代碼示例:
@makeh1
@makeeitalic
def say():
return 'Peter'
咱們但願輸出結果爲:<h1><i>Peter</i></h1>複製代碼
去看看官方文檔,答案就看下面:
def makeh1(func):
def wrp():
return "<h1>" + func() + "</h1>"
return wrp
def makeeitalic(func):
def wrp():
return "<i>" + func() + "</i>"
return wrp
@makeh1
@makeeitalic
def say():
return 'Hello Peter'
print say()
輸出:<h1><i>Hello Peter</i></h1>複製代碼
實際應用場景:
使用過django
的小夥伴想必都用過login_required
裝飾器,可是若是用戶沒登陸的話login_required
會重定向到登陸頁面;在作web開發的過程當中,咱們會常常用
ajax異步提交數據到後臺,這時若是再繼續使用原有的login_required
裝飾器確定是不行了(該裝飾器不會重定向到登陸頁面,ajax也沒有任何返回結果),下面咱們改變下原有代碼:
from django.shortcuts import HttpResponse
import json
def is_authenticat(func):
def wrp(req, **kwargs):
if req.user.is_authenticated():
return func(req, **kwargs)
else:
json_str = {'status': 0, 'msg': u'請登陸'}
return HttpResponse(json.dumps(json_str), content_type='application/json')
return wrp複製代碼
上述代碼便很好的解決了問題,也算是對Python裝飾器的一個很好的使用場景。
Python的奧妙遠不止於此
Python的深度還須要繼續探索
以上就是平時工做中所總結出來的經常使用的知識點
但願對你們之後的工做會有所幫助