目錄
1.盡量用異常來表示特殊情況,而不要返回 none
2.了解如何在閉包裡使用外圍作用域中的變數
2.1閉包相關介紹
2.2獲取閉包內的資料 —— nonlocal語句
3. 考慮用生成器來改寫直接返回列表的函式
4.用數量可變的位置引數減少視覺雜訊
5.用關鍵字引數來表達可選的行為
6.用 none 和文件字串來描述具有動態預設值的引數
7.用只能以關鍵字形式指定的引數來確保**清晰
用 none 這個返回值來表示特殊意義的函式,很容易使呼叫者犯錯,因為none 和 0 以及空字串之類的值,在表示式裡都會評估為 false。函式在遇到特殊情況時,應該丟擲異常,而不要返回 none 。呼叫者在看到該函式的文件中所描述的異常之後,應該就會編寫相應的**來處理它們了。
def divide(a, b):
try:
return a / b
except zerodivisionerror as e:
raise valueerror('invalid inputs') from e # 丟擲異常
x, y = 5, 2
try:
result = divide(x, y)
except valueerror:
print('invalid inputs')
else:
print('result is %.lf' % result)
我們可以將閉包理解為一種特殊的函式,這種函式由兩個函式的巢狀組成,且稱之為外函式和內函式,外函式返回值是內函式的引用,此時就構成了閉包。
def 外層函式(引數):
def 內層函式():
print("內層函式執行", 引數)
return 內層函式
內層函式的引用 = 外層函式("傳入引數")
內層函式的引用()
參考:
1)python比較兩個元組:首先比較各元組中下標為0(第乙個)的對應元素,如果相等,再比較下標為1的對應元素...列表比較也類似。
2)在表示式中引用變數時,python直譯器將按如下順序遍歷各作用域,以解析該引用:
當前函式的作用域。
任何外圍作用域(如:包含當前函式的其他函式)。
包含當前**的那個模組的作用域(即全域性作用域,global scope)。
內建作用域(即包含len 及 str 等函式的那個作用域)。
如果上面這些地方都沒有定義過與名稱相符的變數,就丟擲 nameerror 異常。
nonlocal:在閉包內給變數賦值,會在上層作用域中查詢該變數,在閉包內修改的其實是閉包外那個作用域的變數。nonlocal的唯一限制在於,它不能延申到模組級別。除了那種簡單的函式,盡量不要用 nonlocal 語句,應該將相關狀態封裝成輔助類,也可以利用上面的變數搜尋規則,將變數改為列表型別: 變數名[0] = ?(字典,集合,某個類的例項也類似)。
global:用來表示對該變數的賦值操作,將會直接修改模組作用域裡那個變數。
生成器(generator)是使用 yield 表示式的函式,呼叫生成器函式時,它並不會真正的執行,而是會返回迭代器。每次在這個迭代器上面呼叫內建的 next 函式時,迭代器會把生成器推進到下乙個 yield 表示式那裡。生成器傳給yield的每乙個值,都會由迭代器返回給呼叫者。例,查出字串中每個詞的首字母在整個字串裡的位置。
def index_file(handle):
offset = 0
# 從檔案裡依次讀入各行內容
for line in handle:
if line:
yield offset
# 逐行處理每個單詞
for letter in line:
offset += 1 # 指向letter後乙個位址
if letter == ' ':
yield offest
with open('filepath', 'r') as f:
it = index_file(f)
results = islice(it, 0 , 3) # 迭代前三個
print(list(result))
islice(iterable, [start, ] stop [, step]):
建立乙個迭代器: iterable[start : stop : step],跳過前start個項,迭代在stop所指定的位置停止,step指定用於跳過項的步幅。迭代預設將從0開始,步幅預設1。
注意:迭代器只能使用一輪次。
辦法:1)將迭代器複製乙份列表;2)通過引數來接受另外乙個函式;3)新編一種實現迭代器協議的容器類(python容器)。
*arg: 適用於能夠確定輸入的引數個數比較少時,需要把很多變數或變數名一起傳給某個函式的場合。 關鍵字引數:1)明確引數的含義; 2)在函式定義時提供預設值; 3)提供一種擴充函式引數的有效方式,使得擴充之後的函式依然能夠與原有的那些呼叫的**相相容。注意:可選的關鍵字引數,總是應該以關鍵字形式來指定,而不是以位置引數的形式來指定。
例子:def log(message, when=datetime.now()):
print('%s: %s' % (when, message))
log('hi there!')
sleep(0.1)
log('hi again!')
兩條訊息的時間戳是一樣的,這是因為 datetime.now() 只執行了一次,也就是它只在函式定義的時候執行了一次。引數的預設值,會在每個模組載入進來的時候求出,而很多模組都是在程式啟動時載入的。包括這段**的模組一旦載入進來,引數的預設值就固定不變了,程式不會再次執行 datetime.now()。
應該把預設值設為 none,並在文件字串裡面把 none 所對應的實際行為描述出來。
def log(message, when=none):
"""記錄時間。
args:
message:列印的訊息。
when:時間為 when 列印訊息message,預設為 present time。
"""when = datetime.now() if when is none else when
print('%s: %s' % (when, message))
以下函式引數列表裡的 * 號,標誌著位置引數就此終結,之後的那些引數,都只能以關鍵字形式來指定。
def safe_division_c(number, divisor, *, ignore_overflow=false, ignore_zero_division=false):
# ...
這樣就不能用位置引數的形式來指定關鍵字引數了,關鍵字引數不指定會採取預設值。對於接受多個布林標誌的函式,更應該這樣做。 python總結函式 Python函式之簡單總結
函式的定義 python的函式定義使用關鍵字def,如定義乙個返回絕對值的函式my abs1 5def my abs x if x 0 return x else return x 函式呼叫 引數錯誤 如果在呼叫函式時,傳給函式的引數增多或減少,python直譯器都會檢查出來 typeerror 提...
python之函式總結1
1.空函式 有的時候定義乙個函式,但不會處理什麼業務邏輯,可以這樣 def fun passpass可以看作是乙個佔位符,在if語句中也可以使用。2.引數型別檢查 python內建有乙個函式isinstance 可以對引數型別進行檢查 書寫格式 isinstance x,type x代表要進行型別檢...
python之函式總結2
1.普通引數 示例如下 def counts x print x 這個時候對函式進行呼叫,就必須有乙個對應的實參,否則就會報錯,如下 counts 5 52.含有預設值引數 示例如下 def counts x,n 3 while n 0 x x 1 n n 1 return x這時候,只需傳入對應的...