Python-函数式编程(高阶函数、匿名函数、返回函数、装饰器)_python高阶函数

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上网络安全知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注网络安全)
img

正文

python3没有reduce?不,它被放到了functools模块中,需要导入。这是为什么呢?博主也很好奇,于是去找了一下,原来不止是reduce,python语言的设计者吉多·范罗苏姆(Guido van Rossum)甚至想将lambda、reduce、filter、map函数都删除。

吉多·范罗苏姆(Guido van Rossum)的部分回信内容

最后他只从标准库中删除了reduce,并放到了functools里面。他不想自己设计的语言引入其他语言中抽象复杂的部分,python更多的是作为一种面向对象的脚本语言,而不是函数式编程语言。

参考:The fate of reduce() in Python 3000

filter

filter(functioniterable)

用 iterable 中 传入函数 function返回真的那些元素,构建一个新的迭代器。iterable 可以是一个序列,一个支持迭代的容器,或一个迭代器。如果 function 是 None ,则会假设它是一个身份函数,即 iterable 中所有返回假的元素会被移除。

一句话:利用函数对序列进行过滤/筛选,如同名字一样。

得到一个列表包含100以内的所有素数:

def prime(num):
    tmp = math.sqrt(num)
    i = 2
    while i <= tmp:
        if num % i == 0:
            return False
        i += 1
    return True
t = (range(2, 100))
res = filter(prime, t)
print(type(res))
print(list(res))

结果:

<class ‘filter’>
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

大多数情况下,列表生成式可以完成map和filter的功能。

map 相当于[F(x) for x in S],filter相当于for x in S if P(x)]

t = (range(1, 11))
l = [power(x) for x in t]
l = [power(x,3) for x in t]
t = (range(2, 100))
l = [x for x in t if prime(x)]

有关列表更多内容,可查看:Python-列表总结(操作符、方法、内置函数、相关模块)

匿名函数

一些时候只会在一个地方调用一个很简单的函数,没必要将他们使用def显示的定义出来,这个时候就用到了匿名函数。

Lambda函数可以在需要函数对象的任何地方使用。它们在语法上限于单个表达式。语法如下:

lambda [arg1,arg2,…]:expression

中括号代表可选,也就是说Lambda函数可以有>=0个参数

对于上一篇文章的plus函数:

def plus(a, b):
    return a + b

可以写成:

lambda a,b:a+b

对于power函数,可以写成:

lambda x:x**2

同样,lambda可以作为参数传给其他函数,例如,传给map:

res = map(lambda x: x ** 2, t)

返回函数

说完了函数作为参数,我们就来说说函数作为返回值,也就是返回一个函数。

既然返回一个函数,我们就需要在一个函数中再定义一个函数,有种套娃的感觉。

def plus_not_now(*t):
    def plus_all():
        return sum(t)

    return plus_all


tp = (range(1, 6))
fun = plus_not_now(*tp)
print(type(fun))
print(fun())

我们在plus_not_now中又定义了一个函数plus_all,并将它作为结果返回(注意,不是返回plus_all())。

结果:

<class ‘function’>
15

调用函数fun时才真正运行plus_all的内容。

这里有个奇怪的事情,我们在上面的程序后面再定义一个变量fun2,打印一下两个id

fun2 = plus_not_now(*tp)
print(id(fun))
print(id(fun2))

结果:

<class ‘function’>
15
2005949437416
2005950885320

怎么会不一样呢?这个问题就作为本篇文章的思考题吧!

闭包

当一个内嵌函数引用其外部作用域的变量,我们就会得到一个闭包。创建一个闭包必须满足以下几点:

  1. 必须有一个内嵌函数
  2. 内嵌函数必须引用外部函数中的变量
  3. 外部函数的返回值必须是内嵌函数

前面的返回函数就是闭包

注意,尽量不要引用变化变量

def plus():
    funcs = []
    for i in range(3):
        def add():
            return i + i
        funcs.append(add)
    return funcs


if __name__ == '__main__':
    p1, p2, p3 = plus()
    print(p1(), p2(), p3())

结果为

4 4 4

等你运行p1时,i已经变为了2,不是0,当然,你可以将参数绑定:

def plus():
    funcs = []

    def bind(j):
        def add():
            return j + j

        return add

    for i in range(3):
        funcs.append(bind(i))
    return funcs

装饰器

装饰器:在代码运行前后动态增扩展功能的方式

目前有一些业务已经上线了,现在需要增加验证功能

def add(a, b):
    print(a + b)


def multi(a, b):
    print(a * b)


def devision(a, b):
    print(a / b)

你可能这样写,但如果不让你修改已上线业务代码呢?

def calling(name):
    print(f'{name}正在被调用...')


def add(a, b):
    calling('add')
    print(a + b)


def multi(a, b):
    calling('multi')
    print(a * b)


def devision(a, b):
    calling('devision')
    print(a / b)

你可以这样

def addcalling(func):
    def calling(a, b):
        print(f'{getattr(func, "__name__")}正在被调用...')
        func(a, b)

    return calling


def add(a, b):
    print(a + b)


def multi(a, b):
    print(a * b)


def devision(a, b):
    print(a / b)


if __name__ == '__main__':
    add = addcalling(add)
    add(3, 5)

函数指向了内部函数,multi这些也可以,当然,Python中使用 @装饰器 即可自动让装饰器将下面的函数传入并返回装饰后的函数

def addcalling(func):
    def calling(a, b):
        print(f'{getattr(func, "__name__")}正在被调用...')
        func(a, b)

    return calling

@addcalling
def add(a, b):
    print(a + b)

@addcalling
def multi(a, b):
    print(a * b)

@addcalling
def devision(a, b):
    print(a / b)


if __name__ == '__main__':
    add(3, 5)
    multi(3, 5)
    devision(3, 5)

@addcalling  等价于 func = addcalling(func),所以,即使不运行add(3,5),在解释器解释python代码的过程中碰到@addcalling也会运行addcalling函数

双装饰器

在上面的基础上,再添加一个计算函数运行时间的装饰器

import time


def addcalling(func):
    def calling(a, b):
        print(f'{getattr(func, "__name__")}正在被调用...')
        func(a, b)

    return calling


def addtime(func):
    def runtime(a, b):
        starttime = time.time()
        func(a, b)
        endtime = time.time()
        print(f'运行时间{endtime - starttime}')



## 写在最后

**在结束之际,我想重申的是,学习并非如攀登险峻高峰,而是如滴水穿石般的持久累积。尤其当我们步入工作岗位之后,持之以恒的学习变得愈发不易,如同在茫茫大海中独自划舟,稍有松懈便可能被巨浪吞噬。然而,对于我们程序员而言,学习是生存之本,是我们在激烈市场竞争中立于不败之地的关键。一旦停止学习,我们便如同逆水行舟,不进则退,终将被时代的洪流所淘汰。因此,不断汲取新知识,不仅是对自己的提升,更是对自己的一份珍贵投资。让我们不断磨砺自己,与时代共同进步,书写属于我们的辉煌篇章。**


需要完整版PDF学习资源私我





**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注网络安全)**
![img](https://img-blog.csdnimg.cn/img_convert/4d445548d1e710783fa03ddc53c6d428.png)

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

自划舟,稍有松懈便可能被巨浪吞噬。然而,对于我们程序员而言,学习是生存之本,是我们在激烈市场竞争中立于不败之地的关键。一旦停止学习,我们便如同逆水行舟,不进则退,终将被时代的洪流所淘汰。因此,不断汲取新知识,不仅是对自己的提升,更是对自己的一份珍贵投资。让我们不断磨砺自己,与时代共同进步,书写属于我们的辉煌篇章。**


需要完整版PDF学习资源私我





**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注网络安全)**
[外链图片转存中...(img-nAeA1zvE-1713394395398)]

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值