函数式编程

Python高级特性详解

1. 闭包

闭包,个人理解就是:闭包 = 函数 + 环境变量。
一个简单的闭包例子如下。

def curve_pre():
    a = 25  # 闭包的环境变量
    def curve(x):
        return a * x * x
    return curve

f = curve_pre()	# 返回一个函数
f(3)	# 调用函数
print(f.__closure__[0].cell_contents)    # 取出闭包的环境变量25

闭包的意义,她保存的是一个环境,她把现场保存了下来。

def f1():
     a = 25
     def f2():
         a = 30 # a 此时被认为是一个局部变量,不影响外部a的取值,此时闭包是不存在的
         print(a)	# 打印30
         return a
     print(a)	# 打印25
     f2()
     print(a)	# 打印25
     return f2

f = f1()

一个简单的问题以及解决它的思路,包括不使用闭包和使用闭包两种解决方式。

# 一个问题:一个旅行者,计算路线的长度,x=0代表起点,每走一步加一
# 先走3步,result = 3
# 走5步,result = 8
# 走6步,result = 14
# 问题的关键在于要保存中间过程

# 不用闭包的解决思路
x = 0	# 全局变量


def walk(step):
    global x    # 解决方法是global
    new_x = x + step    # 不加global 这里会报错
    x = new_x   # 不加global,此处x被当做一个局部变量,没有定义,所以会报错
    return x

print(walk(3))
print(walk(5))
print(walk(6))


# 用闭包的方式解决
origin = 0


def factory(pos):
    def go(step):
        nonlocal pos    # 声明pos不是局部变量
        new_pos = pos + step
        pos = new_pos
        return new_pos
    return go

tourist = factory(origin)
print(tourist(3))
print(tourist(5))
print(tourist(6))

2.匿名函数和 三元表达式

借助lambda实现匿名函数。
以下是一个简单的例子,正常函数和匿名函数实现两个数相加,比较之下,显然,匿名函数更加简洁,可读性更高,体现了Python的优势。

def add(x, y):
    return x+y

f = lambda x,y: x+y # 没有名字,不用return,简洁,冒号后面只能是表达式

print(add(1, 2))
print(f(1, 2))

三元表达式

# 三元表达式 x > y ? x : y
# python如何实现三元表达式
r = lambda x,y: x if x>y else y
print(r(2,3))

3. map

# map
# 计算一个列表所有元素的平方
list_x = [1,2,3,4,5,6]
list_y = [1,2,3,4,5,6]

# 第一种方法,传统的方法
def square(x):
    return x * x

for x in list_x:
    print(square(x))

# 用map实现, map会把list中的每一项都传入函数,可以理解为一个映射
m = list(map(square, list_x))
print(m)

# map的真正作用,与lambda一起用,不能提高效率,但代码变得更加简洁
m = list(map(lambda x: x*x, list_x))	# 匿名函数
print(m)

# map的参数可以不止一个
m = list(map(lambda x,y:x*x+y, list_x, list_y))
print(m)

4. reduce

# reduce
from functools import reduce
r = reduce(lambda x,y:x+y, list_x)  # 连续计算,连续调用lambda,每一次计算结果变成下一次计算的参数
# ((1+2)+3)+ ....
print(r)

5. filter

# filter: 过滤
list_x = [1,0,1,0,0,1]
r = list(filter(lambda x: True if x == 1 else False, list_x))   # 返回False,过滤0
print(r)	# [1, 1, 1], 过滤了0

6. 装饰器

# 装饰器:最有用的高阶知识
import time


def f1():	# 一个简单的函数,先输出时间,再打印信息
    print(time.time())  # 一个时间戳
    print('this is a function')
f1()


# 假如有100个函数同时要打印time.time()呢,难道要写100次?显然不行!
def f2():
    print('this is a function')


def f3():
    print('this is a function')


def print_current_time(func):   # 接收一个函数参数
    print(time.time())
    func()

# 这种方法其实本质上并没有改变
print_current_time(f2)
print_current_time(f3)


# 如何更优雅的实现呢, 这就是装饰器的好处
import time
def decorator(func):
    def wrapper(*args, **kw):  # 接收可变参数和关键字参数,装饰器才有意义
        print(time.time())
        func(*args, **kw)
    return wrapper

f = decorator(f2)	# 但是这种调用方式也是很麻烦,如何改进?
f()


# 如何更优雅的实现呢
@decorator
def f4():
    print('this is a function')

f4()    # 没有改变原来调用的方式


# 如果f函数有参数呢,装饰器要做什么改变吗,要把装饰器的内置函数变成可变参数*args
@decorator
def f5(func_name):
    print('this is a function:' + func_name)

f5('fun1')


@decorator
def f6(func_name1, func_name2):
    print('this is a function:' + func_name1)
    print('this is a function:' + func_name2)

f6('fun1','fun2')


# 如果f函数有关键字参数呢,装饰器要做什么改变吗,要把装饰器的内置函数加上**kw关键字参数
@decorator
def f7(func_name1, func_name2, **kw):   # kw是关键字参数
    print('this is a function:' + func_name1)
    print('this is a function:' + func_name2)
    print(kw)

f7('testfun1', 'testfun2', a=1, b=2, c='123')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值