函数作为返回值

可变参数的求和

可以不返回求和的结果,而是返回求和的函数:

不需要立刻求和,而是在后面的代码中,根据需要再计算

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

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,返回值就是该表达式的结果。

用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数

装饰器

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可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。