【python3的学习之路九】函数式编程

变量作用域

变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。Python的作用域一共有4种,分别是:

  • L (Local) 局部作用域
  • E (Enclosing) 闭包函数外的函数中
  • G (Global) 全局作用域
  • B (Built-in) 内建作用域

以 L –> E –> G –>B 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。

x = int(2.9)  # 内建作用域

g_count = 0  # 全局作用域
def outer():
    o_count = 1  # 闭包函数外的函数中
    def inner():
        i_count = 2  # 局部作用域

global和nonlocal关键字

当内部作用域想修改外部作用域的变量时,就要用到global和nonlocal关键字。

num = 1
def fun1():
    global num  # 需要使用 global 关键字声明
    print(num)
    num = 123
    print(num)
fun1()
print(num)

如果要修改嵌套作用域(enclosing作用域,外层非全局作用域)中的变量nonlocal关键字,如下:

def outer():
    num = 10
    def inner():
        nonlocal num   # nonlocal关键字声明
        num = 100
        print(num)
    inner()
    print(num)
outer()

传入函数

变量也可以指向函数,函数的参数能接受变量,那么一个函数就可以接受另一个函数作为参数,这种函数就称之为高阶函数。

def add(x, y, f):
    print(f(x) + f(y))

add(-5, 6, abs)   # 11
  • map

map()函数接受俩个参数,一个是函数,一个是Iterator,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator。

def f(x):
    return x * x

r = map(f, [1, 2, 3, 4, 5])
print(r)   # [1, 4, 9, 16, 25]
print(list(map(str, [1, 2, 3, 4, 5])))   # [‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘]
  • filter

filter()函数用于过滤序列。filter()函数也接受一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True和False决定保留还是丢弃元素。

def is_odd(n):
     return n % 2 == 1

def not_empty(s):
    return s and s.strip()

print(list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])))     # [1, 5, 9, 15]
print(list(filter(not_empty, [‘A‘, ‘‘, ‘b‘, ‘ ‘, ‘c‘, None]))) #[‘A‘, ‘b‘, ‘c‘]

注意:filter()函数转换成list

练习题:取出1~1000中的回数。回数是指从左向右读和从右向左读都是一样的数,例如12321,909。

def get(l):
    s = str(l)
    return s == s[::-1]  # 请回顾切片

print(list(filter(get, range(1,1000))))
  • sorted

sorted()函数可以对list进行排序

sorted([36, 5, -12, 9, -21])  # [-21, -12, 5, 9, 36]
sorted([36, 5, -12, 9, -21], key = abs) #[5, 9, -12, -21, 36]
sorted([‘bob‘, ‘about‘, ‘Zoo‘, ‘Credit‘]) # [‘Credit‘, ‘Zoo‘, ‘about‘, ‘bob‘] 对字符串排序,是按照ASCII的大小比较的
sorted([‘bob‘, ‘about‘, ‘Zoo‘, ‘Credit‘], key = str.lower) # [‘about‘, ‘bob‘, ‘Credit‘, ‘Zoo‘]
sorted([‘bob‘, ‘about‘, ‘Zoo‘, ‘Credit‘], key = str.lower, reverse = True) # [‘Zoo‘, ‘Credit‘, ‘bob‘, ‘about‘]

返回函数

当我们调用c时返回的是求和函数,每次调用都会返回一个新的函数,即使传入相同的参数,所以f1和f2调用的结果互不影响。

def c(*args):
    def sum():
        ax = 0
        for n in args:
           ax = ax + n
        return ax
    return sum

print(c(1, 3, 4, 5, 6)())
f1 = c(1, 3, 5, 7, 9)
f2 = c(1, 3, 5, 7, 9)
print(f1 == f2)   # False

匿名函数

  • 关键字lambda表示匿名函数,冒号前面的x表示函数参数。
  • 匿名函数只能有一个表达式,不用写return,返回值就是该表达式的结果
  • 匿名函数没有名字,不必担心函数名冲突
  • 匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数
list(map(lambda x: x * x, [1, 2, 3, 4, 5]))
# def f(x):
#     return x * x

def build(x, y):
    return lambda: x * x + y * y

装饰器

在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。

我们定义一个能打印日志的decorator——log,它能接受一个函数作为参数,并返回一个函数。调用time()函数,不仅会运行now()函数本身,还会在运行now()函数前打印一行日志。

def log(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print(‘call %s():‘ %func.__name__)
        return func(*args, **kwargs)
    return wrapper

@log             # 相当执行语句now = log(now)
def time():
    print(‘2015-12-09‘)

如果decorator本身需要传入参数、那么需要编写一个返回decorator的高阶函数。比如,要自定义log的文本。

def log(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            print(‘%s %s():‘ %(text, func.__name__))
            return func(*args, **kwargs)
        return wrapper
    return decorator

@log(‘execute‘)           # 相当执行语句now = log(‘execute‘)(now)
def time():
    print(‘2015-12-09‘)

因为返回的那个wrapper()函数名字就是’wrapper’,所以,需要把原始函数的__name__等属性复制到wrapper()函数中,否则,有些依赖函数签名的代码执行就会出错。

不需要编写 wrapper._ name_ = func.__name__这样的代码,Python内置的functools.wraps就是干这个事的。

偏函数

通过设定参数的默认值,可以降低函数调用的难度,而偏函数就可以做到这一点。

假设要转换大量的二进制字符串,每次都传入++int(x, base = 2)++非常麻烦,我们就可以定义一个函数,把默认的base = 2传进去

def int2(x, base = 2)
    return int(x, base)

functools.partial就帮助我们创建一个偏函数,不需要我们自定义int2()

import functools
int2 = functools.partial(int, base = 2)

原文地址:https://www.cnblogs.com/CSgarcia/p/9706136.html

时间: 2024-11-08 14:00:55

【python3的学习之路九】函数式编程的相关文章

Python学习之路:函数式编程介绍&高阶函数

函数式编程:一种抽象程度很高的范式,重要特点:输入是确定的,输出就是确定的: Python对函数式编程,部分支持: 高阶函数: def add(x,y,f):#函数本身传给函数,就是高阶函数 return f(x)+f(y) res = add(3,-6,abs) print(res)

linux学习之路之脚本编程知识点

脚本编程知识点 1.获取变量中字符的长度 ${#VARNAME} 2.变量赋值 ${parameter:-word}:如果parameter为空或者未定义,则整个表达式为word:否则表达式值为parameter ${parameter:+word}:如果parameter为空或者未定义,则整个表达式为空:如果parameter有值,则整个表达式为word ${parameter:=word}:如果parameter为空或者未定义,则整个表达式值为parameter:否则整个表达式值为word

Python学习总结之五 -- 入门函数式编程

函数式编程 最近对Python的学习有些怠慢,最近的学习态度和学习效率确实很不好,目前这种病况正在好转. 今天,我把之前学过的Python中函数式编程简单总结一下,分享给大家,也欢迎并感谢大家提出意见. 首先,我们学习函数式编程时,需要知道一个概念:高阶函数.那么到底什么是高阶函数呢?把函数作为参数传入,这样的函数就称为高阶函数.而函数式编程就是指这种高度抽象的编程范式. 正文 接下来,我简单介绍以下四种函数的用法:map/reduce   filter   sorted   lambda 在这

python学习09-函数和函数式编程

函数和函数式编程 函数会向调用者返回一个值, 而实际编程中大偏函数更接近过程,不显示地返回任何东西.把过程看待成函数的语言通常对于"什么都不返回"的函数设定了特殊的类型或者值的名字.这些函数在 c 中默认为"void"的返回类型,意思是没有值返回. 在 python 中, 对应的返回对象类型是none. 简而言之,当没有显式地返回元素或者如果返回 None 时, python 会返回一个 None.那么调用者接收的就是 python 返回的那个对象,且对象的类型仍然

《JS权威指南学习总结--8.8 函数式编程和8.8.1使用函数处理数组》

内容要点:    和Lisp.Haskell不同,JS并非函数式编程语言,但在JS中可以像操控对象一样操控函数,   也就是说可以在JS中应用函数式编程技术.ES5中的数组方法(诸如map()和reduce())就可以非常适用于函数式编程风格. 一.使用函数处理数组    假设有一个数组,数组元素都是数字,我们想要计算这些元素的平均值和标准差.    若用非函数式编程风格的话,代码是这样:         var data = [1,1,3,5,5]; //这里是待处理的数组        //

学习日志---python(函数式编程)

函数式编程 后面的闭包和装饰器很重要,参数可以是函数,把函数传进去参与运算. 过程是一个没有返回值的函数,函数本身也是一个对象,因此可以赋值给引用: 一个模块中函数不可重名,因此不支持重载,因为python是以函数名来识别调用的哪一个: 模块中函数的定义是自上而下的: 可以多个返回值,看作是一个元组:也可以分开多个变量接受返回值: def p():     return 1,2,3 a=p() print a a,b,c=p() print a,b,c 函数的属性 文档属性:__doc__ 可以

python学习第十一天 -- 函数式编程

在介绍函数式编程之前,先介绍几个概念性的东西. 什么是函数式编程? 函数式编程的特点: 1.把计算视为函数而非指令; 2.纯函数式编程:不需要变量,没有副作用,测试简单; 3.支持高阶函数,代码简洁. 什么是高阶函数? 能接收函数做参数的函数,称为高阶函数. 高阶函数的特点: 1.变量可以指向函数 2.函数的参数可以接收变量 3.一个函数可以接收另一个函数作为参数 Python支持的函数式编程? 1.不是纯函数式编程:允许有变量 2.支持高阶函数:函数也可以作为变量传入 3.支持闭包:有了闭包就

Python进阶学习(一)——函数式编程

1.函数式编程 函数:function 函数式:functional,一种编程范式 函数≠函数式 函数式编程的特点: 把计算视为函数而非指令. 纯函数式编程:不需要变量,没有副作用,测试简单. 支持高阶函数,代码简洁. Python支持的函数式编程: 不是纯函数式编程:允许有变量. 支持高阶函数:函数key作为变量传入. 支持闭包:有了闭包就能返回函数. 有限度的支持匿名函数. 2.高阶函数 变量可以指向一个函数. >>> abs(-10) 10 >>> abs <

Python3学习之路~6.1 编程范式:面向过程 VS 面向对象

编程范式 编程是程序员用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程,一个程序是程序员为了得到一个任务结果而编写的一组指令的集合,正所谓条条大路通罗马,实现一个任务的方式有很多种不同的方式,对这些不同的编程方式的特点进行归纳总结得出来的编程方式类别,即为编程范式.不同的编程范式本质上代表对各种类型的任务采取的不同的解决问题的思路, 大多数语言只支持一种编程范式,当然也有些语言可以同时支持多种编程范式.两种最重要的编程范式分别是面向过程编程和面向对象编程. 面向过程编程(Pr