有基础学Python > 0x4 函数式编程

学习“廖雪峰的官方网站:Python教程”时做的笔记

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# 变量指向的对象可以是函数。
# 函数名其实就是指向函数的变量。
# builtins.abs = 10 在其他模块也会生效,导致无法计算绝对值。
# 高阶函数:函数接收另一个函数作为参数。
def add(x, y, f):
    return f(x) + f(y)


# map
iterator = map(abs, range(-5, 5)) # 返回map object,是惰性的Iterator
print(list(iterator))


# reduce
from functools import reduce
reduce(pow, range(2, 5))
# 2,3,4 -> 2^3,4 = 8,4 -> 8^4 = 4096

DIGITS = {
    
    '0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9 }
# s = ''
# for i in range(48, 58):
#     temp = '\'' + chr(i) + '\':' + str(i-48) + ','
#     print(temp)
#     s = s + temp
# print(s)

def char2num(s):
    return DIGITS[s]

def str2int(s):
    return reduce(lambda x, y: x * 10 + y, map(char2num, s))
    # return reduce(lambda x, y: x * 10 + y, map(lambda x: DIGITS[x], s))

# lambda匿名函数:func(x, y) => x * 10 + y
print(str2int('1314'))


# filter
# 返回惰性序列。
# 函数返回值为True时取,否则舍。
print(list(filter(lambda x: x % 2 == 0, range(10))))


# sorted
# 默认升序,reverse反向,可接收key函数实现自定义排序。
print(sorted([3, -1, 8, -5], key = abs, reverse = True))


# 返回函数
def lazy_sum(*args): 
    def sum():
        # 可以访问args,闭包结构。
        ax = 0 
        pass
        return ax
    return sum

f = lazy_sum(range(5)) # 每次调用lazy_sum返回不同的函数对象。
f() # 被调用时才计算,万一不调用呢?就不用计算、节省资源。

# 使用闭包时牢记:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
# 一定要引用循环变量时,内层再套一个函数并返回。
# 内层函数能访问外层函数的变量,但不能修改变量的指向(修改list内容不会改变指向),除非使用nonlocal关键字。
def createCounter():
    n = 0   # n = [0] 也可
    def counter():
        nonlocal n
        n += 1
        return n
    return counter


# 装饰器Decrator
# 不改变函数定义的前提下,增强函数功能,比如调用前后记录日志。
# 函数对象有一个__name__属性,可以拿到函数的名字。
import functools
# 3层装饰器
def log(text):  # 自定义日志文本,故加一层
    def decorator(func):
        @functools.wraps(func)  # 相当于wrapper.__name__=func.__name__。相当于wrapper = functools.wraps(func)(wrapper)?
        def wrapper(*args, **kw):   # 该参数组合可以接收任意参数
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator

@log('执行')    # 相当于 now = log('执行')(now), 新now是wrapper。
def now():
    print('2021-6-17')

now()
print(now.__name__) # 新now是wrapper。wrapper.__name__==func.__name__。

# 以下合并2层、3层装饰器
from inspect import isfunction
def logg(*text):

    # 3层
    def decoratorWithFunc(func):
        @functools.wraps(func)  # 相当于wrapper.__name__=func.__name__。相当于wrapper = functools.wraps(func)(wrapper)?
        def wrapper(*args, **kw):   # 该参数组合可以接收任意参数
            print('begin call %s():' % (func.__name__))
            for arg in text:
                print(arg)
            x = func(*args, **kw)
            print('end call')
            return x
        return wrapper
    # return decoratorWithFunc

    # 2层
    def wrapper(*args, **kw):   # 该参数组合可以接收任意参数
        func = text[0]
        print('begin call %s():' % (func.__name__))
        # for arg in text:
        #     print(arg)
        x = func(*args, **kw)
        print('end call')
        return x
    # return wrapper

    # 兼容2层和3层
    # print(isfunction(text[0]))
    if len(text) > 0 and isfunction(text[0]):
        return wrapper
    return decoratorWithFunc

@logg('执行', 'execute')   # logg('执行')(f)
# @logg           # logg(f)
# @logg()
def f():
    print('f being called')
    pass

print('*****兼容2、3层')
f()


# 偏函数
# 参数个数太多时,可以固定部分参数,得到简化。
int2 = functools.partial(int, base=2)   # 增加类似int(str, base=10)的函数。
print(int2('110')) # 2^2 + 2^1 + 2^0 = 6

猜你喜欢

转载自blog.csdn.net/qq_33067925/article/details/120424664