三元操做符:
咱們都知道在C語言中,三元操做符爲C ? X : Y
,在人們的強烈要求下,python2.5以後三元操做符等價爲X if C else Y
。python
何時應該使用斷言?
斷言的基本語法以下: assert expression1 ["," expression2]
計算expression1的值會返回True或者False,當值爲False的時候會引起AssertError,而expression2是可選的,經常使用來查看具體的異常信息。
斷言是有代價的,會對性能產生必定的影響,但python並無嚴格定義調試與發佈模式之間的差異,一般禁用斷言的方法是在運行腳本時加上-O標誌,這種方法帶來的影響是它不優化字節碼,而是忽略與斷言有關的語句。
斷言是用來捕獲用戶定義的約束的,不是用來捕獲程序自己的錯誤的。express
斷言應該被使用在正常邏輯不可到達的地方或正常狀況下老是爲真的場合。app
異常能處理就不要使用斷言。函數
不要用斷言檢查用戶輸入。性能
當函數調用後,須要肯定返回值是否合理時可使用斷言。優化
當條件是業務邏輯繼續的先決條件時可使用斷言。調試
我最近在一個爬蟲代碼裏使用了幾回斷言,使用斷言是爲了保證程序自身所記錄的頁數與爬蟲所運行到的頁數相同,不然會在存儲數據時發生錯誤。code
數據交換值時不推薦使用中間變量 x,y = y,x
這種方法有更好的性能。 對象
構建合理的包層次來管理module
本質上每個python文件都是一個模塊,但在大的項目中把全部的python文件放在一個目錄下不是一個好的作法。咱們應該用package包來管理模塊。 __init__.py
的一些做用:內存
Package/ __init__.py Module1.py Module2.py Subpackage/ __init__.py Module1.py Module2.py
使包和普通目錄區分
若是咱們在Package包下的__init__.py
中添加: from Module1 import Test
語句,則能夠直接使用from Package import Test
來導入類Test
當__init__.py
爲空,意圖使用from Package import *
語句將包Package
中全部的模塊導入當前命名空間將會失敗。它僅僅會執行__init__.py
文件。所以咱們須要修改__init__.py
文件。
若是咱們在__init__.py
文件中添加:
__all__ = ['Module1','Module2','Subpackage']
這樣咱們就能使用from Package import *
語句將包Package
中全部的模塊導入當前命名空間。
使用with自動關閉資源
with語句能夠在代碼塊執行完畢後還原進入該代碼塊時的現場。在文件管理時使用with總能保證文件被正常關閉。
None的特殊性
全部被賦值爲None的變量相等,而且None與任何其餘非None的對象比較結果都爲False.
字符串的鏈接特別是大規模字符串的處理,應該優先使用join而不是+。
若是咱們進行如下操做:S1+S2+S3+..
,執行一次+操做便會在內存中申請一塊新的內存,並將上一次操做的結果和本次操做的右操做數複製到該內存中。在N個字符串鏈接中,會產生N-1箇中間結果,每產生一箇中間結果都要申請和複製一次內存,總共要申請N-1次內存,嚴重影響效率。時間複雜度接近O(n^2)。
而當使用join()方法鏈接字符串時,會首先計算須要申請的總的內存空間,而後一次性申請所需內存並將字符序列中的每個元素複製到內存中。時間複雜度爲O(n)。
python中一切皆對象,每個對象都有一個惟一的id。
函數傳參既不是傳值也不是傳引用
在C/C++中,若是執行:
a = 5; b = a; b = 7;
在內存中申請一塊內存並將a的值複製到該內存中,當執行b = 7時將b對應的值從5改到7。
而對於python,賦值並非複製,b=a使得a和b引用同一個對象。b=7則是將b指向對象7。
python函數參數究竟是傳值仍是傳引用,實際都不是,而是傳對象或者說傳對象的引用。
對可變對象的修改在函數外部以及內部均可見,調用者和被調用者之間共享這個對象。
對於不可變對象,因爲並不能真正修改,由於,修改每每是經過生成一個新對象而後賦值來實現的。
警戒默認參數潛在的問題
def在python中是一個可執行的語句,當解釋器執行def時,默認參數也會被計算,並存在函數的.func_defaults屬性中。 因爲Python中函數參數傳遞的是對象,可變對象在調用者和被調用者之間共享。
def appendtest(newitem,lista=[]): print(id(lista)) lista.append(newitem) print(id(lista)) return lista >>> appendtest(1) 12345 12345 [1] >>> appendtest('a') 12345 12345 [1,'a']
PS:咱們能夠用這個屬性,統計某個方法被調用的次數。
若是不想讓默認參數所指向的對象在全部的函數調用中共享,而是在函數調用的過程當中動態生成,可在定義的時候使用None對象做爲佔位符。
def appendtest(newitem,lista=None): print(id(lista)) lista.append(newitem) print(id(lista)) return lista
str()和repr()的區別:目標不一樣:str()面向用戶,repr()面向解釋器和開發人員
字符串的一些技巧:
python遇到未閉合的小括號時會自動將多行代碼拼接爲一行和把相鄰的兩個字符串字面量拼接在一塊兒。
s = ('SELECT * ' 'FROM atable ' 'WHERE afirld="value"') print(s) >>> SELECT * FROM atable WHERE afirld="value"
str的一些方法
str方法不少,只說幾個有意思的:
count()能查找子串在字符串中出現的次數,這個方法在調用replace方法時能使用,能夠批量替換。
replace(old,new[,count])用以替換字符串的某些子串,若是指定count參數,就最多替換count次,不指定則替換所有。
參考資料:《編寫高質量代碼:改善Python程序的91個建議》