闭包:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数+相关外部变量就被认为是闭包(closure)。
例:函数f内嵌套函数sub_f,但是子函数fsub_f引用了外部函数f的变量。注意,若函数f返回值为sub_f,则多次返回会创建不同的函数。
参考:http://www.jb51.net/article/86383.htm
装饰器:在闭包的基础上传递了一个函数(见下文func),然后覆盖原来函数的执行入口(nei_hanshu的参数canshu),以后调用这个函数(login)的时候,就可以额外实现一些功能了。一般在原函数的前,或者后增加功能,不改变原函数内部的功能。
目的:为了不修改原函数(login)的代码,也不修改其他调用这个函数的代码,就能实现功能的拓展(调用外部不同的func)。
适用性:当为一个函数前前后后增加功能时,
参考:http://www.jb51.net/article/65774.htm http://www.jb51.net/article/134598.htm
装饰器的另一种写法,语法糖,@zsq=(login=zsq(login)):
带参数的装饰器:
装饰器的嵌套:
也就是从上到下的嵌套了。
同时为装饰多个函数功能,并一起工作
注意:
1.函数的参数传递的其实是引用,而不是值。
2.函数名也是一个变量,所以可以重新赋值。
3.赋值操作的时候,先执行等号右边的。
4. @函数名 是python的一种语法糖。执行@后的函数f之前,将@下的函数low_f作为参数传入f内,在将f的返回值返回给下面的函数名low_f
Python不可变数据结构:tuple
定义:函数仅接受输入并产生输出,不包含任何能影响产生输出的内部状态。
特点:
- 避免边界效应:程序输出只依赖于输入,不使用在程序运行时可变的数据结构
- 任何情况下,使用相同的参数调用函数始终能产生同样的结果。
- 允许把函数本身作为参数传入另一个函数,还允许返回一个函数
纯函数式编程:完全没有边界效应,函数没有变量
对比:
面向对象编程:包含内部状态(成员变量)和修改状态的函数(成员函数),程序运行过程中,可以不断的修改内部状态
函数式编程 :xx
高阶函数背景:
变量可以指向函数名:函数结果返回给变量x = abs(-10); 函数名返回给变量:f = abs
函数名其实就是指向函数的变量:若将abs指向10,比如abs = 10,则abs(-10)会报错
高阶函数:
就可以接收另一个函数作为参数的函数,函数式编程就是指这种高度抽象的编程范式。如:
def add(x, y, f):
return f(x) + f(y)
add(-5, 6, abs)
高阶函数map函数:迭代依次操作序列中每个元素,返回一个新的迭代器?接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次独立的作用到序列的每个元素,并把结果作为新的Iterator返回【独立作用每个元素】
案例:list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
高阶函数reduce函数:迭代按函数的要求,操作序列中每个元素,返回一个操作结果,值?把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累计计算【结果依赖前后元素之间复用】
reduce第二个参数为任何实现了__iter__()方法的可迭代对象。如果不指定第三个参数,则第一次调用function将使用iterable的前两个元素作为参数。
案例:
reduce(add, [1, 3, 5, 7, 9]) #return 1+3 return 4+5 return 9+7 return 16+9
all(iterable) == reduce(lambda x, y: bool(x and y), iterable)
any(iterable) == reduce(lambda x, y: bool(x or y), iterable)
max(iterable[, args...][, key]) == reduce(lambda x, y: x if key(x) > key(y) else y, iterable_and_args)
min(iterable[, args...][, key]) == reduce(lambda x, y: x if key(x) < key(y) else y, iterable_and_args)
sum(iterable[, start]) == reduce(lambda x, y: x + y, iterable, start)
map()+reduce()
案例:
from functools import reduce
def fn(x, y):
return x * 10 + y
def char2num(s):
digits = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
return digits[s]
reduce(fn, map(char2num, '13579')) # 注意string,list,dict,tuple都是可迭代对象
高阶函数filter()函数:用于过滤序列。filter接收一个函数和一个序列。与map不同,把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。【独立作用每个元素】且该操作位于最终处理完之后一起处理??迭代器指针会变化么?
案例:
def is_odd(n):
return n % 2 == 1
list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])) # 删掉偶数,只保留奇数
zip(iterable1, iterable2, ...):函数返回一个列表,每个元素都是一个元组,包含(iterable1[n], iterable2[n], ...)
例如:zip([1, 2], [3, 4]) --> [(1, 3), (2, 4)]
如果参数的长度不一致,将在最短的序列结束时结束;如果不提供参数,将返回空列表。
高阶函数sort(使用默认的数据或自定义映射函数处理后的数据,进行正序或者逆序排序):
sorted()函数就可以对list进行排序:
案例:sorted([36, 5, -12, 9, -21])
可以接收一个key函数来实现自定义的排序,key指定的函数将作用于list的每一个元素上,并根据key函数返回的结果(list或新list)进行排序:
案例:sorted([36, 5, -12, 9, -21], key=abs)
sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower)
进行反向排序,不必改动key函数,可以传入第三个参数reverse=True:
案例:sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)
返回函数:即可以在函数f1中,定义函数sub_fx,根据需求参数,返回不同函数sub_fx。注意,每次调用f1,返回的是不同的实例。
def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum
>>> f1 = lazy_sum(1, 3, 5, 7, 9)
>>> f2 = lazy_sum(1, 3, 5, 7, 9)
>>> f1==f2
匿名函数:为了编写偶尔为之的、简单的、可预见不会被修改的匿名函数
lambda表达式定义一个匿名的函数,如果这个函数仅在编码的位置使用到,你可以现场定义、直接使用:
关键字lambda表示匿名函数,冒号前面的x表示函数参数
限制:就是只能有一个表达式,不用写return,返回值就是该表达式的结果。
优点:函数没有名字,不必担心函数名冲突;匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数。如 f = lambda x: x * x;也可以把匿名函数作为返回值返回;匿名函数常常结合map,reduce,fileter一起使用
案例:lst.sort(lambda o1, o2: o1.compareTo(o2)) # 输入o1,02, 输出冒号后面的操作的结果
生成器:
生成器就是一种迭代器。生成器拥有next方法并且行为与迭代器完全相同,这意味着生成器也可以用于Python的for循环中。
生成器可以挂起,所以是延迟计算的,在yield外面加while True无限循环并没有关系。
加入了yield的函数叫做生成器函数,第一次调用生成器的next方法时,生成器才开始执行生成器函数,,直到遇到yield时暂停执行(挂起),并且yield的参数将作为此次next方法的返回值;
http://www.jb51.net/article/68319.htm
偏函数
为避免每次传入base=2的写法,可将int(“123‘’,base=2)写作:
functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。
当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。