Fork me on GitHub

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

posted @ 2019-08-13 14:06  cznczai  阅读(264)  评论(0编辑  收藏  举报