# 7.1 可接受任意数量参数的函数 # 注意,*参数后面仍然可以定义其他参数 def b(x, *args, y, **kwargs): pass # 7.2 只接受关键字参数的函数(命名关键字参数,强制关键字参数) # 希望函数的某些参数强制使用关键字参数传递,将该参数放到某个*参数或者单个*后面就可以 def recv(maxsize, *, block): print('receives a message') # recv(1024,True) # TypeError: recv() takes 1 positional argument but 2 were given,说明只接收一个位置参数 recv(1024,block=True) help(recv) # 7.3 给函数参数增加元信息 def recv(maxsize:int, *, block:bool) -> int: print('receives a message') help(recv) recv(1024,block=True) # 7.4 函数返回多个值,直接用元组,return时不需要加() def func(): return 1,2,3 for j in func(): print(j) # 7.5 定义有默认参数的函数 x = 42 def spam(a, b=x): print(a, b) spam(1) x = 23 spam(1) # 输出还是42,默认参数的值仅仅在函数定义的时候赋值一次 # 默认参数的值应该是不可变的对象,不能是[]等可变的对象 def spam(a, b=[]): print(b) return b x = spam(1) print(x) x.append(99) spam(1) # 判断一个参数是否是None的时候要用 is None,不能not b,否则空字符串、列表、元组、字典not的值都是True # 微妙的问题:判断某个可选参数是否被用户传递进来 _no_vlue = object() def spam(a, b=_no_vlue): if b is _no_vlue: print('No b value supplied') spam(1) # 7.6定义匿名或内联函数 # lambda只能定义单个表达式 names = ['David Beazley', 'Brian Jones','Raymond Aettinger', 'Ned Batchelder'] print(sorted(names,key=lambda name: name.split()[-1].lower())) # 7.7 匿名函数捕获变量值 x = 10 a = lambda y: x+y # x在运行时才绑定值,而不是定义时绑定 x = 20 b = lambda y: x+y print(a(10),b(10)) # 如果想lambda函数参数在定义时就捕获到值,将参数定义成默认参数 x = 10 a = lambda y,x=x: x+y # x在运行时才绑定值,而不是定义时绑定 x = 20 b = lambda y,x=x: x+y print(a(10),b(10)) x = 10 def c(y): return x+y # 结果一样,x在运行时才绑定值,而不是定义时绑定 x = 20 def d(y): return x+y print(c(10),d(10)) # 7.8减少可调用对象的参数个数 # functool.partial() from functools import partial def spam(a, b, c, d): print(a, b, c, d) s1 = partial(spam, 1) s1(2, 3, 4) s2 = partial(spam,d=10) s2(1,2,3) # 7.9 将单方法的类转化为函数:使用闭包 from urllib.request import urlopen class UrlTemplate: def __init__(self, template): self.template = template def open(self, **kwargs): return urlopen(self.template) baidu = UrlTemplate('https://www.baidu.com') for line in baidu.open(name='IBM,APPL,FB',fields='sl1c1v'): # print(line.decode('utf-8')) pass # 7.10 带额外状态信息的回调函数 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 apply_async(add,(2,3),callback=print_result) # 让回调函数访问外部信息 # 方法1:使用一个绑定方法来代替一个简单函数 class ResultHandler: def __init__(self): self.sequence = 0 def handler(self,result): self.sequence += 1 print('[{}] Got:{}'.format(self.sequence, result)) r = ResultHandler() apply_async(add,(2,3),callback=r.handler) # 方法2:作为类的替代,使用一个闭包捕获状态值 def make_handler(): sequence = 0 def handler(result): nonlocal sequence sequence += 1 print('[{}] Got:{}'.format(sequence, result)) return handler handler = make_handler() apply_async(add,(2,3),callback=handler) # 方法3:使用协程达到同样的效果 def make_handler2(): sequence = 0 while True: result = yield sequence += 1 print('[{}] Got:{}'.format(sequence, result)) handler2 = make_handler2() next(handler2) # 启动协程 apply_async(add,(2,3),callback=handler2.send) # 7.11内敛回调函数 TODO 看不懂! # 使用生成器和协程可以使得回调函数内联在某个函数中 # def apply_async(func, args, *, callback): # result = func(*args) # callback(result) # # from queue import Queue # from functools import wraps # # class Async: # def __init__(self, func, args): # self.func = func # self.args = args # # def inlined_async(func): # @wraps(func) # def wrapper(*args): # f = func(*args) # result_queue = Queue() # result_queue.put(None) # while True: # result = result_queue.get() # try: # a = f.send(result) # apply_async(a.func, a.args, callback=result_queue.put) # except StopIteration: # break # return wrapper # 7.12 访问闭包中定义的变量 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 f = sample() f() f.set_n(10) f() print(f.get_n()) def f1(): n = 3 print('in f1') def f2(): print(n) print('in f2') return 3 return f2 print(f1()())
【Python Cookbook学习笔记】 第七章 函数
最新推荐文章于 2024-12-18 17:39:02 发布