函數(shù)
可接受任意數(shù)量參數(shù)的函數(shù)
- 可以使用 * 使函數(shù)接收任意數(shù)量的位置參數(shù), * 只能是函數(shù)的最后一個(gè)位置參數(shù)
- 可以使用 ** 使函數(shù)接收任意數(shù)量的關(guān)鍵字參數(shù) ** 只能是函數(shù)的最后一個(gè)參數(shù)
def func(x, *args, **kwargs):
print (x)
print (args)
print (kwargs)
if __name__ == '__main__':
func(1, 2, 3, four=4)
out:
1
(2, 3)
{'four': 4}
只接受關(guān)鍵字參數(shù)的函數(shù)
def recv(num, block=None):
pass
msg = recv(1024, block=False)
定義有默認(rèn)參數(shù)的函數(shù)
- 使用_no_value賦值給object()測(cè)試某個(gè)參數(shù)是否傳遞了進(jìn)來(lái)
- 傳遞None 和 不傳遞參數(shù)是有差別的
_no_value = object()
def spam(a, b=_no_value):
if b is _no_value:
print ('No b value supplied')
print (a)
if __name__ == '__main__':
spam(1)
spam(1, 2)
spam(1, None)
out:
No b value supplied
1
1
1
- 默認(rèn)參數(shù)的值應(yīng)該是不可變的對(duì)象(None, True, Flase,數(shù)字或字符串)
- 使用可變對(duì)象傳值,可能會(huì)無(wú)意間修改傳遞的默認(rèn)值
ERROR!
def spam(a, b=[]):
print (b)
return b
out:
>>> x = spam(1)
[]
>>> x.append(99)
>>> x.append('Yow!')
>>> x
[99, 'Yow!']
>>> spam(1)
[99, 'Yow!']
- 在檢查None的時(shí)候使用is 操作符否則0, '',都會(huì)被檢測(cè)為None
def spam(a, b=None):
#Error
if not b:
pass
#correct
if b is None:
pass
定義匿名或內(nèi)聯(lián)函數(shù)(lambda)
- lambda 只能指定單個(gè)表達(dá)式,他的值就是最后的返回值
>>> add = lambda x, y:x+y
>>> add(2, 3)
5
>>> add('hell', 'o')
'hello'
#根據(jù)名的來(lái)進(jìn)行排序
>>> names = ['David Beazley', 'Brian Jones','Raymond Hettinger', 'Ned Batchelder']
>>> sorted(names, key=lambda name:name.split()[-1].lower())
['Ned Batchelder', 'David Beazley', 'Raymond Hettinger', 'Brian Jones']
匿名函數(shù)捕獲變量值
- lambda定義一個(gè)匿名函數(shù),定義時(shí)捕獲到某些變量值
- lambda中的x是一個(gè)自由變量,在運(yùn)行時(shí)綁定
>>> x = 10
>>> a = lambda y:x+y
>>> x = 20
>>> a(10)
30
- 在lambda中綁定默認(rèn)值 main(),funcs函數(shù)列表的n值都不同
def main():
#根據(jù)lambda 生成函數(shù)
funcs = [lambda x, n=n:x+n for n in range(5)]
for f in funcs:
print (f(0))
def main1():
funcs = [lambda x :x+n for n in range(5)]
for f in funcs:
print (f(0))
out:
0,1,2,3,4
減少函數(shù)的參數(shù)個(gè)數(shù)
- 使用functools.partial()減少函數(shù)的調(diào)用參數(shù)值
- partial會(huì)返回一個(gè)新的函數(shù)對(duì)象,新的函數(shù)會(huì)合并已經(jīng)賦值的參數(shù),最后傳遞給原始函數(shù)
def spam(a, b, c, d):
print (a, b, c, d)
>>> s1 = partial(spam, d=42)
>>> s1(1, 2, 3)
1 2 3 42
將單方法的類轉(zhuǎn)換為函數(shù)
- class 中除了init()外,只定義了一個(gè)方法
- 使用類的原因是需要存儲(chǔ)一些額外的值給template調(diào)用,比如本例中的template
- 在閉包中,一個(gè)閉包就是一個(gè)函數(shù),閉包會(huì)記住自己在定義時(shí)的環(huán)境,在本例中opener()函數(shù)記住了template變量
- 給函數(shù)使用閉包比使用類更加簡(jiǎn)潔
from urllib.request import urlopen
class UrlTemplate:
def __init__(self, template):
self.template = template
def open(self, **kwargs):
return urlopen(self.template.format_map(kwargs))
def urltemplate(template):
def opener(**kwargs):
return urlopen(template.format_map(kwargs))
return opener
if __name__ == '__main__':
yahoo = UrlTemplate('http://finance.yahoo.com/d/quotes.csv?s={names}&f={fields}')
for line in yahoo.open(names='IBM,AAPL,FB', fields='sl1c1v'):
print (line.decode('utf-8'))
yahoo = urltemplate('http://finance.yahoo.com/d/quotes.csv?s={names}&f={fields}')
for line in yahoo(names='IBM,AAPL,FB', fields='sl1c1v'):
print (line.decode('utf-8'))
帶額外狀態(tài)信息的回調(diào)函數(shù)
- 為了讓回調(diào)函數(shù)訪問(wèn)外部信息草描,可以給回調(diào)函數(shù)綁定一個(gè)額外的方法,通過(guò)訪問(wèn)類的所屬變量來(lái)達(dá)到目的
def apply_async(func, args, *, callback):
result = func(*args)
callback(result)
def print_result(result):
print ('Got:', result)
def add(x, y):
return x + y
class ResultHandler:
def __init__(self):
self.sequence = 0
def handler(self, result):
self.sequence += 1
print ('[{}] Got:{}'.format(self.sequence, result))
if __name__ == '__main__':
apply_async(add, (2, 3), callback=print_result)
#通過(guò)類方法來(lái)訪問(wèn)外部信息
r = ResultHandler()
apply_async(add, (2, 3), callback=r.handler)
apply_async(add, ('hello', 'world'), callback=r.handler)
- 可以使用閉包來(lái)代替類方法來(lái)捕獲狀態(tài)值
-
nonlocal 聲明可以改變閉包中的參數(shù)值,這里是sequence += 1
def apply_async(func, args, *, callback):
result = func(*args)
callback(result)
def add(x, y):
return x + y
def make_handler():
sequence = 0
def handler(result):
nonlocal sequence
sequence += 1
print('[{}] Got: {}'.format(sequence, result))
return handler
if __name__ == '__main__':
#使用閉包捕獲狀態(tài)值
handler = make_handler()
apply_async(add, (2, 3), callback=handler)
apply_async(add, ('hello', 'world'), callback=handler)
訪問(wèn)閉包中定義的變量,并且可以修改
- 閉包的內(nèi)部變量對(duì)于外界是完全隱藏的,但可以編寫訪問(wèn)函數(shù)并將函數(shù)綁定到閉包上實(shí)現(xiàn)
- 函數(shù)屬性允許我們用一種很簡(jiǎn)單的方式將訪問(wèn)方法綁定到閉包函數(shù)上覆糟,這個(gè)跟實(shí)例方法很像
def sample():
n = 0
def func():
print ('n=', n)
def get_n():
return n
def set_n(value):
nonlocal n
n = value
func.get_n = get_n
func.set_n = set_n
return func
out:
>>> f = sample()
>>> f()
n= 0
>>> f.set_n(10)
>>> f()
n= 10
>>> f.get_n()
10