python返回函数+匿名函数+装饰器+偏函数
函数作为返回值
可变参数的求和
可以不返回求和的结果,而是返回求和的函数:
不需要立刻求和,而是在后面的代码中,根据需要再计算
def sum_nums(*args): sum = 0 for i in args: sum = sum + i return sum def lazy_sum(*args): def sum_nums(): ax = 0 for i in args: ax = ax + i return ax return sum_nums if __name__ == '__main__': print(sum_nums(1, 2, 3, 4, 5)) #15 print(lazy_sum(1,2,3,4,5)) #.sum_nums at 0x000001D547F8B6A8> 返回的是函数 运行的时候需要调用函数 f1 = lazy_sum(1, 3, 5, 7, 9) f2 = lazy_sum(1, 3, 5, 7, 9) print(f1==f2) #False
闭包
注意到返回的函数在其定义内部引用了局部变量args,所以,当一个函数返回了一个函数后,其内部的局部变量还被新函数引用,所以,闭包用起来简单,实现起来可不容易。另一个需要注意的问题是,返回的函数并没有立刻执行,而是直到调用了f()才执行。
def fun(): print("hello") def fun1(): # 作用域 运行时存活 函数执行期间 print("world") #想让fun1 调用 需要用 return fun1() / fun1
https://www.bilibili.com/video/av18586448?from=search&seid=6307915518193049229
def count(): fs = [] for i in range(1, 4): def f(): return i*i fs.append(f) return fs f1, f2, f3 = count() #9 9 9 经过初步的检验得出 存到 fs 是 三个 f 的 地址 已经有进行运行 所以 f1 f2 f3 只是让里面的函数进行运行 #ValueError: too many values to unpack (expected 2) 需要有三个函数输入并同时返回三个函数,等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9 #闭包 def count(): def fun1(j): def fun2(): return j*j print(j,fun2()) return fun2 ls = [] for i in range(1,4): ls.append(fun1(i)) return ls if __name__ == '__main__': a,b,c = count() print(a()) print(b()) print(c()) ''' 1 1 2 4 3 9 1 4 9 ''' #计数器 def createCounter(): i = 0 def counter(): nonlocal i i += 1 return i return counter
匿名函数
关键字lambda表示匿名函数,冒号前面的x表示函数参数。
匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。
用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数
装饰器
增强now()函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改now()函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。
函数对象有一个name属性,可以拿到函数的名字
https://www.bilibili.com/video/av25698102/
https://www.jianshu.com/p/98f7e34845b5
https://v.youku.com/v_show/id_XNDMwNjczNjExMg==.html
import time # 时间未加装饰器 def is_prime(x): if x < 2 : return False elif x == 2 : return True else : for i in range(2 , x): if x % i == 0: return False return True def print_nums(): a = time.time() for i in range(2 ,10000 ): if is_prime(i): print(i) b = time.time() print(b-a) if __name__ == '__main__': print_nums()
改成时间的装饰器
def display_time(func): def wrapper(): #包装:wrapper 其实这里可以替代为其他的名字 a = time.time() func() # 只是装饰器就是这样的结构 b = time.time() print(b - a) return wrapper # 对其wrapper 这里返回wrapper 如果下面 print_nums不加括号 wrapper要加 反之不加 @display_time def print_nums(): for i in range(2 ,10000 ): if is_prime(i): print(i) if __name__ == '__main__': print_nums()
继续变形
def display_time(func): def wrapper(): a = time.time() result = func() # 星星 b = time.time() print(b - a) return result return wrapper @display_time def print_nums(): count = 0 for i in range(2 ,10000 ): if is_prime(i): count = count+1 return count # 星星 返回除去给func 后给 result if __name__ == '__main__': print(print_nums()) #调用即运行 后输出result 给 wrapper 就不会输出none
加参数的操作
def display_time(func): def wrapper(*args): # 星星 a = time.time() result = func(*args) # 星星 b = time.time() print(b - a) return result return wrapper @display_time def print_nums(nums): # 星星 count = 0 for i in range(2 ,nums ): # 星星 if is_prime(i): count = count+1 return count if __name__ == '__main__': print(print_nums(10000)) #调用即运行 后输出result 给 wrapper
wrapper()函数的参数定义是(args, *kw),因此,wrapper()函数可以接受任意参数的调用
三层嵌套
import functools def log (func): #@functools.wraps(func) 有得话 house 无则 wrapper 消除装饰器的副作用 def wrapper(): return func() return wrapper @log def house(): print(house.__name__) house() 小结 在面向对象(OOP)的设计模式中,decorator被称为装饰模式。OOP的装饰模式需要通过继承和组合来实现,而Python除了能支持OOP的decorator外,直接从语法层次支持decorator。Python的decorator可以用函数实现,也可以用类实现。 decorator可以增强函数的功能,定义起来虽然有点复杂,但使用起来非常灵活和方便。 @functools.wraps(func) 消除副作用
偏函数
Python的functools模块提供了很多有用的功能,其中一个就是偏函数(Partial function)
- int()函数可以把字符串转换为整数,当仅传入字符串时,int()函数默认按十进制转换 int('123456')
- 但int()函数还提供额外的base参数,默认值为10。如果传入base参数,就可以做N进制的转换 int('123456 ' , base = 8) / ,16
functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),可以直接使用下面的代码创建一个新的函数:
import functools int2 = functools.partial(int , base = 2) print(int2('11101'))
当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。