高阶函数

话说当年C语言和Java里好像都有这么个东西...忘了

一句话说就是函数名本身就是一个引用. 可以作为变量传递.

一个简单的例子:

  1. def power_demo(x): 


  2. return x*x 



  3. def foo(num1,num2,fun): 


  4. return fun(num1) + fun(num2) 



  5. print(foo(2,3,power_demo)) 



map/reduce的用法

map()方法

map(function, iterable, ...)

Return an iterator that applies function to every item of iterable, yielding the results. If additional iterable arguments are passed, function must take that many arguments and is applied to the items from all iterables in parallel. With multiple iterables, the iterator stops when the shortest iterable is exhausted. For cases where the function inputs are already arranged into argument tuples, see itertools.starmap().

解读:

入参是一个函数和一个可迭代对象. 函数依次作用于可迭代对象上.

返回值是一个迭代器

  1. def f(x): 


  2. return x*x 


  3. L = map(f,[1,2,3,4,5,6]) 


  4. print(type(L)) 


  5. print(list(L)) 



reduce()方法

functools.reduce(function, iterable[, initializer])

Apply function of two arguments cumulatively to the items of sequence, from left to right, so as to reduce the sequence to a single value.

For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates ((((1+2)+3)+4)+5).

The left argument, x, is the accumulated value and the right argument, y, is the update value from the sequence. If the optional initializer is present, it is placed before the items of the sequence in the calculation, and serves as a default when the sequence is empty. If initializer is not given and sequence contains only one item, the first item is returned.

文档中给出的大概的实现

  1. def reduce(function, iterable, initializer=None): 


  2. it = iter(iterable) 


  3. if initializer is None: 


  4. value = next(it) 


  5. else: 


  6. value = initializer 


  7. for element in it: 


  8. value = function(value, element) 


  9. return value 



一个例子:

  1. from functools import reduce 



  2. def foo(x,y): 


  3. return x*10+y 


  4. result = reduce(foo,[1,3,5,7,9]) 



  5. print(type(result),result) 



filter()方法

filter(function, iterable)

Construct an iterator from those elements of iterable for which function returns true. iterable may be either a sequence, a container which supports iteration, or an iterator. If function is None, the identity function is assumed, that is, all elements of iterable that are false are removed.

Note that filter(function, iterable) is equivalent to the generator expression (item for item in iterable if function(item)) if function is not None and (item for item in iterable if item) if function is None.

先来个简单的例子,筛选奇数

  1. def is_odd(x): 


  2. return x%2 ==1 



  3. print(list(filter(is_odd,[1,2,3,4,5,6,7,8,9]))) 



举个例子,比如使用传说中的埃拉托色尼筛选法筛选出所有素数

  1. def odd_iter(): 


  2. n = 1 


  3. while True: 


  4. n = n + 2 


  5. yield n 



  6. def not_divisible(n): 


  7. return lambda x: x % n > 0 



  8. def primes(): 


  9. yield 2 


  10. it = odd_iter() 


  11. while True: 


  12. n = next(it) 


  13. yield n 


  14. it = filter(not_divisible(n), it) 



sorted()函数

自定义排序的一个函数. 举个简单的例子吧,感觉一是半会儿用不上.


  1. sorted([36, 5, -12, 9, -21], key=abs,reverse=True) 



python中的闭包

变量的作用域

不写了,回头发文章补齐

嵌套函数

函数里套函数,发文章的时候补齐

什么是闭包

看维基百科的学术定义

在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。

说啥呢看不懂...

举个例子:

  1. def print_msg(): 


  2. msg = "hello world" 


  3. def printer(): 


  4. print(msg) 


  5. # 注意,这里没带括号,返回的是printer()这个函数的引用(指针) 


  6. return printer 



  7. # 这里等于通过print_msg()拿到了内部函数printer()的引用,所以printer这个变量指向了一个叫printer的函数 


  8. printer = print_msg() 


  9. print(printer) 


  10. printer() 




pic-1582723050329.png

不是所有嵌套函数都是闭包,就如同不是所有牛奶都是...跑题了

看箭头的位置,按照剧本,当函数执行完成后,其内部的局部变量应该已经销毁.

也就是说在print_msg()这函数执行完了之后,msg这个变量应该不存在了.

但是,BUT!!!

当我们通过print_msg()返回的引用去执行其内部的函数printer()的时候,msg这个变量又神奇的被打印出来了.

这里的printer变量就是一个闭包.

以下是我个人的理解,如果有错误,烦请指出. 因为python的GC使用的是引用计数机制.

所以当我们执行printer = print_msg()的时候,虽然print_msg()函数执行完了,但是在执行过程中,创建了一个字符串对象'hello world' (并将其引用赋值给了msg)和一个函数对象printer. 然后printer中又保留了到字符串对象msg的引用.所以在执行上述语句的时候发生了这么一个关系printer(外面的变量,这个名字起瞎了)-->printer--->msg

所以在函数print_msg执行完毕之后,变量msg的引用并没有变成0,这个变量依旧存在,没有被GC处理掉.

闭包有啥用

闭包避免了使用全局变量. 闭包允许函数将与其操作的某些数据(环境))关联起来.

在面向对象的编程中,对象允许我们将一些数据(属性)和一个或多个方法关联起来.

但是当对象中只有一个方法的时候,使用闭包或许是更好的选择.

  1. def foo(x): 


  2. def foo_inner(y): 


  3. return x+y 


  4. return foo_inner 



  5. foo1 = foo(5) 



  6. print(foo1(10)) 


  7. print(foo1(6)) 




pic-1582723050329.png

匿名函数

就是lambda表达式. lambda 入参 : 返回值

冒号前面是入参,冒号后面是返回值.用来简写函数的. 比如

  1. L = list(map(lambda x:x*x,[1,2,3,4,5])) 


  2. print(L) 



不好理解,新手别瞎JB用

装饰器

面向对象的语言中,万物都是对象,方法(函数)当然也是一个对象. 是对象就要有属性方法和引用. 函数对象有一个__name__的属性可以拿到函数的名称.

  1. def now():     


  2. print("2020-02-18") 


  3. foo = now 



  4. print(foo.__name__) 


  5. print(now.__name__) 



这俩输出肯定是一样的. 不懂的话C语言基础(非谭浩强版)从头学

那么如果现在我们想增强now()方法的功能,除了重写这个方法之外还有没有其他的办法?

想想嵌套函数貌似是可以的.

  1. def log(func): 


  2. def wrapper(*args, **kw): 


  3. #这里是我们想增强的代码 


  4. print('this is a log: function "%s" is called'%func.__name__) 


  5. return func(*args, **kw) 


  6. return wrapper 



  7. @log 


  8. def now(): 


  9. print("2020-02-18") 



这玩意儿就有点装饰器的样子了.

在now函数上面写个@log实际上就是在执行 log(now())

但是有个问题.

改造后的代码就是这个样子的.

  1. import functools 


  2. def log(func): 


  3. @functools.wraps(func) 


  4. def wrapper(*args, **kw): 


  5. #这里是我们想增强的代码 


  6. print('this is a log: function "%s" is called'%func.__name__) 


  7. return func(*args, **kw) 


  8. return wrapper 



  9. @log 


  10. def now(): 


  11. print("2020-02-18") 



  12. print(now.__name__) 



这里我们又发现一个神器的东西. 就是装饰器functools.wraps带参数...这玩意儿咋实现的呢?

看个例子:

  1. def log(text): 


  2. def decoraotor(func): 


  3. @functools.wraps(func) 


  4. def wrapper(*args, **kwargs): 


  5. print("%s %s" % (text, func.__name__)) 


  6. return func(*args, **kwargs) 


  7. return wrapper 


  8. return decoraotor 



  9. @log("Holy shit!") 


  10. def now(): 


  11. print("2020-02-18") 



真特么复杂...用到的时候翻笔记吧. 记不住记不住

偏函数

python中的偏函数不是数学上的偏函数(话说数学上的偏函数是啥,我也不知道...),看文档定义:

functools.partial(func, /, *args, **keywords)

Return a new partial object which when called will behave like func called with the positional arguments args and keyword arguments keywords. If more arguments are supplied to the call, they are appended to args. If additional keyword arguments are supplied, they extend and override keywords. Roughly equivalent to:

  1. def partial(func, /, *args, **keywords): 


  2. def newfunc(*fargs, **fkeywords): 


  3. newkeywords = {**keywords, **fkeywords} 


  4. return func(*args, *fargs, **newkeywords) 


  5. newfunc.func = func 


  6. newfunc.args = args 


  7. newfunc.keywords = keywords 


  8. return newfunc 



The partial() is used for partial function application which “freezes” some portion of a function’s arguments and/or keywords resulting in a new object with a simplified signature. For example, partial() can be used to create a callable that behaves like the int() function where the base argument defaults to two:

  1. from functools import partial 


  2. basetwo = partial(int, base=2) 


  3. basetwo.__doc__ = 'Convert base 2 string to an int.' 


  4. basetwo('10010') 



partial Objects

partial objects are callable objects created by partial(). They have three read-only attributes:

partial.func

A callable object or function. Calls to the partial object will be forwarded to func with new arguments and keywords.

partial.args

The leftmost positional arguments that will be prepended to the positional arguments provided to a partial object call.

partial.keywords

The keyword arguments that will be supplied when the partial object is called.

partial objects are like function objects in that they are callable, weak referencable, and can have attributes. There are some important differences. For instance, the__name__ and __doc__attributes are not created automatically. Also, partial objects defined in classes behave like static methods and do not transform into bound methods during instance attribute look-up.

看一个例子就得了.高级玩法,新手别瞎JB玩.

  1. def int2(x,base=2): 


  2. return int(x,base) 


  3. print(int2('10000000')) 



  4. int22 = functools.partial(int,base=2) 


  5. print(int22('10000000')) 



python随用随学20200118-函数的高级特性的更多相关文章

  1. C++复习11.函数的高级特性

    C++ 函数的高级特性 20131002 C++函数增加了重载(override), inline, const, virtual四种机制,重载和内联机制既可以用于全局函数,也可以用于类的成员函数.c ...

  2. python:函数的高级特性

    很多语言中,都允许把函数本身做为参数,传递给其它参数:即所谓的高阶函数.python中也有类似特性: 一.map/reduce.filter.sorted hadoop里的map-reduce思想在p ...

  3. Python序列函数、高级特性及高阶函数

    序列函数: enumerate: for循环时记录索引,逐个返回元组(i, item) sorted:返回新的有序列表 zip:压缩将多个序列的对应位置的元素组成元组 zip(*元组列表): 解压缩 ...

  4. 002-python函数、高级特性

    1.函数 1.1 定义函数 在Python中,定义一个函数要使用def语句,依次写出函数名.括号.括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回 自定义一个求绝对 ...

  5. python学习-33 max和min函数的高级使用

    1.简单比较 age_dic={'age1456':15,'age2':16,'xiaohong_age':12,'xiaoming_age4':18,'age5':10} print(max(age ...

  6. C++函数的高级特性

    对比于 C 语言的函数,C++增加了重载(overloaded).内联(inline).const 和 virtual 四种新机制.其中重载和内联机制既可用于全局函数也可用于类的成员函数,const ...

  7. C++函数的高级特性——小结

    相对于C语言,C++增加了重载(overload).内联(inline).const和virtual四种新机制. 1 重载 只能靠参数列表而不能紧靠返回值类型的不同来区分重载函数.编译器根据参数列表为 ...

  8. Python学习教程(Python学习视频_Python学些路线):Day06 函数和模块的使用

    Python学习教程(Python学习视频_Python学些路线):函数和模块的使用 在讲解本章节的内容之前,我们先来研究一道数学题,请说出下面的方程有多少组正整数解. $$x_1 + x_2 + x ...

  9. Python之旅Day3 文件操作 函数(递归|匿名|嵌套|高阶)函数式编程 内置方法

    知识回顾 常见五大数据类型分类小结:数字.字符串.列表.元组.字典 按存值个数区分:容器类型(列表.字典.元组) 标量原子(数字.字符串) 按是否可变区分:可变(列表.字典) 不可变(数字.字符串.元 ...

随机推荐

  1. Python第一个请求接口

    1.普通get请求 import requests import json login_res=requests.post(url='http://joy.web.com:8090/login',da ...

  2. C# 根据年月日计算周次

    //day:要判断的日期,WeekStart:1 周一为一周的开始, 2 周日为一周的开始 public static int WeekOfMonth(DateTime day, int WeekSt ...

  3. vue需要知道哪些才能算作入门以及熟练

    前两天接到一个面试官问我vue什么程度才算作可以用于开发,以前从没遇到过类似问题.只能大致说了一些,事后觉得也应该总结一下,前端vue这么火热那究竟什么才算做入门什么才算做熟练,只是我个人观点,不代表 ...

  4. 代码审计之CVE-2018-7600-Drupal远程代码执行漏洞-Render API

    今天学习一下Drupal的另一个漏洞,由于渲染数组不当造成的漏洞 poc: url:http://localhost/drupal-8.5.0/user/register?element_parent ...

  5. Perl语言入门(中文版)(第6版) 东南大学出版社

    第一章简介 问题与答案 这本书适合你吗? 为何有这么多的脚注? 关于习题和解答? 习题前标的数字是什么意思? 如果我是Perl讲师? “Perl”这个词表示什么意思? Larry为什么要创造Perl? ...

  6. Android的学习之路一

    在Android的道路上越走越远==,本着一颗童心去学习,没想到最后会成为自己的职业.看到过知乎上写的,并不是兴趣使比尔盖茨以及乔布斯他们成就斐然,而是他们真正的牛逼使得即使买大饼也能成为世界首富.然 ...

  7. SSM前后端分离/不分离对比Demo

    之前某些原因,整理了一个小的Demo,用于演示.个人认为在SSM前后端不分离的基础上在前端处理上比较麻烦一点之后就是注解的使用.总结一些对比,仅是自己掌握的,不够严谨,不足之处请大佬批评指正. 路由控 ...

  8. c#数字图像处理(一)Bitmap类、 Bitmapdata类和 Graphics类

    Bitmap类. Bitmapdata类和 Graphics类是C#图像处理中最重要的3个类,如果要用C#进行图像处理,就一定要掌握它们. 1.1 Bitmap类Bitmap对象封装了GDI+中的一个 ...

  9. Centos 7 最小化部署svn版本控制(http协议)

    1.关闭selinux sh-4.2# sed -i 's/enforcing/disabled/' /etc/selinux/config sh-4.2# reboot 2.卸载防火墙 sh-4.2 ...

  10. time 模块 和 random 模块常用方法讲解

    import timeprint(help(time))print(time.time())#时间戳 1573991312.5361328print(time.perf_counter())#计算CP ...