標籤:
定義 返回單值
def my_abs(x): if x >= 0: return x else: return -x
返回多值
返回多值就是返回一個tuple
import mathdef move(x, y, step, angle=0): nx = x + step * math.cos(angle) ny = y - step * math.sin(angle) return nx, ny
空函數
def nop(): pass
指定預設參數
必選參數在前,預設參數在後。預設參數需指向不可變對象(預設參數值在函數定義時被計算)
def power(x, n=2): s = 1 while n > 0: n = n - 1 s = s * x return s
可變參數
def calc(*numbers): sum = 0 for n in numbers: sum = sum + n * n return sum
調用可變參數的函數方法
>>> calc(1, 2)5>>> calc()0>>> nums = [1, 2, 3]>>> calc(*nums)14
關鍵字參數
def person(name, age, **kw): print ‘name:‘, name, ‘age:‘, age, ‘other:‘, kw
調用關鍵字參數的方法
>>> person(‘Michael‘, 30)name: Michael age: 30 other: {}>>> person(‘Bob‘, 35, city=‘Beijing‘)name: Bob age: 35 other: {‘city‘: ‘Beijing‘}>>> person(‘Adam‘, 45, gender=‘M‘, job=‘Engineer‘)name: Adam age: 45 other: {‘gender‘: ‘M‘, ‘job‘: ‘Engineer‘}>>> kw = {‘city‘: ‘Beijing‘, ‘job‘: ‘Engineer‘}>>> person(‘Jack‘, 24, **kw)name: Jack age: 24 other: {‘city‘: ‘Beijing‘, ‘job‘: ‘Engineer‘}
註:
- 參數定義的順序必須是:必選參數、預設參數、可變參數和關鍵字參數。
- 對於任意函數,都可以通過類似
func(*args, **kw)
的形式調用它,無論它的參數是如何定義的。
遞迴
如果一個函數在內部調用自身本身,這個函數就是遞迴函式。
尾遞迴
在函數返回的時候,調用自身本身,並且,return語句不能包含運算式。
高階函數
- 變數可以指向函數(函數可以賦值給一個變數)
- 函數名也是變數(函數名可以賦值其他值)
- 函數可以做為函數的參數(高階函數)
map(func, list)
map()函數接收兩個參數,一個是函數,一個是序列,map將傳入的函數依次作用到序列的每個元素,並把結果作為新的list返回。
>>> def f(x):... return x * x...>>> map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])[1, 4, 9, 16, 25, 36, 49, 64, 81]
reduce(func_with_two_params, list)
reduce把一個函數作用在一個序列[x1, x2, x3…]上,這個函數必須接收兩個參數,reduce把結果繼續和序列的下一個元素做累積計算。
reduce(f, [x1, x2, x3, x4])#相當於:f(f(f(x1, x2), x3), x4)>>> def add(x, y):... return x + y...>>> reduce(add, [1, 3, 5, 7, 9])25
filter(func_return_bool, list)
把傳入的函數依次作用於每個元素,然後根據傳回值是True還是False決定保留還是丟棄該元素。
def is_odd(n): return n % 2 == 1filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])# 結果: [1, 5, 9, 15]
sorted
對於兩個元素x
和y
,如果認為x < y
,則返回-1
,如果認為x == y
,則返回0
,如果認為x > y
,則返回1
,
>>> sorted([36, 5, 12, 9, 21])[5, 9, 12, 21, 36]
高階函數用法
def reversed_cmp(x, y): if x > y: return -1 if x < y: return 1 return 0>>> sorted([36, 5, 12, 9, 21], reversed_cmp)[36, 21, 12, 9, 5]
函數做為傳回值
def lazy_sum(*args): def sum(): ax = 0 for n in args: ax = ax + n return ax return sum>>> f = lazy_sum(1, 3, 5, 7, 9)>>> f<function sum at 0x10452f668>>>> f()25
註:每次調用lazy_sum()
都會返回一個新的函數,即使傳入相同的參數。
閉包
def count(): fs = [] for i in range(1, 4): def f(): return i*i fs.append(f) return fsf1, f2, f3 = count()>>> f1()9>>> f2()9>>> f3()9
原因是調用count的時候迴圈已經執行,但是f()
還沒有執行,直到調用其時才執行。所以返回函數不要引用任何迴圈變數,或者後續會發生變化的變數。
匿名函數(lambda運算式)
lambda x: x * x
等價於:
def f(x): return x * x
關鍵字lambda
表示匿名函數,冒號前面的x
表示函數參數。
匿名函數做為傳回值
def build(x, y): return lambda: x * x + y * y
裝飾器(@func)
在代碼運行期間動態增加功能的方式,稱之為“裝飾器”(Decorator),本質上,decorator就是一個返回函數的高階函數。
def log(func): def wrapper(*args, **kw): print ‘call %s():‘ % func.__name__ return func(*args, **kw) return wrapper@logdef now(): print ‘2013-12-25‘>>> now()call now():2013-12-25#相當於執行:now = log(now)
帶參數的裝飾器
def log(text): def decorator(func): def wrapper(*args, **kw): print ‘%s %s():‘ % (text, func.__name__) return func(*args, **kw) return wrapper return decorator@log(‘execute‘)def now(): print ‘2013-12-25‘#執行結果>>> now()execute now():2013-12-25#相當於執行:>>> now = log(‘execute‘)(now)
剖析:首先執行log(‘execute‘)
,返回的是decorator
函數,再調用返回的函數,參數是now
函數,傳回值最終是wrapper
函數。
__name__
由於函數的__name__
已經改變,依賴於此的代碼就會出錯。因此使用functools.wraps
。
import functoolsdef log(func): @functools.wraps(func) def wrapper(*args, **kw): print ‘call %s():‘ % func.__name__ return func(*args, **kw) return wrapper#對於帶參函數import functoolsdef log(text): def decorator(func): @functools.wraps(func) def wrapper(*args, **kw): print ‘%s %s():‘ % (text, func.__name__) return func(*args, **kw) return wrapper return decorator
偏函數(固定函數預設值)
>>> import functools>>> int2 = functools.partial(int, base=2)>>> int2(‘1000000‘)64>>> int2(‘1010101‘)85#相當於:def int2(x, base=2): return int(x, base)max2 = functools.partial(max, 10)
相當於為max
函數指定了第一個參數
max2(5, 6, 7)#相當於:max(10, 5, 6, 7)
Python學習筆記-函數篇