高阶函数

话说当年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. 阿里巴巴Jetcache springboot使用教程

    原文地址:https://www.jianshu.com/p/03b289439de2 springboot中使用说明 jetcache原理参见:https://www.jianshu.com/p/8 ...

  2. GeoGebra学习-lesson1

    我曾经想过学习数学的时候总觉得不太直观,希望通过直观的图形来直观的学习数学.庆幸的是,在B站看视频时看到了妈咪叔使用了这款数学软件,很好用的样子.就去简单的了解了一下,下面是摘抄自<Geogeb ...

  3. CentOS7.0+Hadoop2.7.2+Hbase1.2.1搭建教程

    1.软件版本 CentOS-7.0-1406-x86_64-DVD.iso jdk-7u80-linux-x64.tar.gz hadoop-2.7.2.tar.gz hbase-1.2.1-bin. ...

  4. [校内训练19_09_02]A

    题意 给出N 个形如$f_i(x) = a_i x^2 + b_i x $的二次函数. 有Q 次询问,每次给出一个x,询问$max{\{f_i(x)\}}$.$N,Q \leq 5*10^5$. 思考 ...

  5. node使用art-template的过滤器

    引言 art-template过滤器在我看来,其实就是定义一个函数,模板字符串通过调用该函数处理相关的数据,得到相应的返回结果,显示在页面上.因此我们可以注册一个过滤器,处理相关的数据.这里使用nod ...

  6. 五、spring源码阅读之ClassPathXmlApplicationContext加载beanFactory

    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml&q ...

  7. 深入并发锁,解析Synchronized锁升级

    这篇文章分为六个部分,不同特性的锁分类,并发锁的不同设计,Synchronized中的锁升级,ReentrantLock和ReadWriteLock的应用,帮助你梳理 Java 并发锁及相关的操作. ...

  8. 理解和运用Java中的Lambda

    前提 回想一下,JDK8是2014年发布正式版的,到现在为(2020-02-08)止已经过去了5年多.JDK8引入的两个比较强大的新特性是Lambda表达式(下文的Lambda特指JDK提供的Lamb ...

  9. JSP&Servlet学习笔记----第5章

    Servlet进阶API 每个Servlet都必须由web容器读取Servlet设置信息(标注或者web.xml).初始化. 对于每个Servlet的设置信息,web容器会为其生成一个ServletC ...

  10. CCF_201403-1_相反数

    按绝对值排序,因为没相同的数,直接遍历比较一遍即可. #include<iostream> #include<cstdio> #include<algorithm> ...