目录
首先了解两个概念
变量可以指向函数
例2.1.1:
>>> abs
<built-in function abs>
>>> a = abs
>>> a(-1)
1
分析:函数本身可以赋值给变量。上述例子中被赋值的变量a
可以当做abs
函数本身来使用。
函数名也是变量
例2.1.2:
>>> abs = 10
>>> abs(-1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
分析:这里的函数名abs
指向了数字10后,我们再以函数的形式调用它,就已经不起作用了,因为abs已经不指向求绝对值的函数,而是指向了10这个整数!说明函数名本身也是变量。
搞懂了上面两个概念后,我们再回过头来看高阶函数。
一个函数可以接受另一个函数作为参数,这种函数就是高阶函数
。
例2.1.3:
#!/user/bin/python
#coding=utf-8
_author_ = "zjw"
#一个计算两个列表总长度的高阶函数函数
def allLen(x, y, fun):
return fun(x) + fun(y)
if __name__ == "__main__":
li1 = [1, 2, 3]
li2 = [4, 5]
print allLen(li1, li2, len)
输出
5
分析:上述高阶函数allLen
是一个计算两个列表长度总和的函数。该函数将len
函数作为参数传入到allLen
函数中,所以是一个高阶函数。
基本形式:map(function, Iterable);
function
指某个特定的函数。Iterable
,即凡是可以使用for循环的对象都是Iterable类型的。如list, tuple, dict, set, str等。map函数返回一个Iterator
(即凡是可以使用next()函数的对象都是Iterator类型的)。
Iterator
是一个惰性序列,所以在返回值时可以使用list()
函数把整个序列编程一个list型。函数说明:map将传入的函数依次作用到序列的每一个元素,并把结果作为新的Iterator返回。
实例
例2.2.1:
#!/user/bin/python
#coding=utf-8
_author_ = "zjw"
if __name__ == "__main__":
li = [-1, -3, 2, -3]
newList = list(map(abs, li))
print newList
输出:
[1, 3, 2, 3]
分析:上面例子中,map函数的作用是将abs函数作用于li列表的每一个元素,返回一个全部都是绝对值的新列表newList;这里在map函数外还嵌套了一个list函数的作用是将惰性序列转化为列表。
基本形式:reduce(function, Iterable);
function
指某个特定函数。Iterable
的说明如上。reduce函数返回的是一个值。
函数说明:。reduce
把一个函数作用在一个序列[x1, x2, x3, ...]
上,这个函数必须接收两个参数,reduce
把结果继续和序列的下一个元素做累积计算,效果如下:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
实例
例2.3.1:
#!/user/bin/python
#coding=utf-8
_author_ = "zjw"
def add(x, y):
return x + y
if __name__ == "__main__":
li = range(11)
sum = reduce(add, li)
print sum
输出
55
分析:这里的reduce函数是将add函数作为功能函数,一开始传入两个li的元素,得到结果与li的下一个元素再传入add函数中,以此类推,得到最后的总和的结果。
基本形式:filter(function, Iterable);
函数返回一个Iterator
。
函数说明:filter()
把传入的函数依次作用到每一个元素上,然后根据函数的返回值是True还是False决定保留还是丢弃该元素。即就像一个过滤器一样,过滤掉我们不想要的元素。
实例:
例2.4.1:
#!/user/bin/python
#coding=utf-8
_author_ = "zjw"
#判断是否为偶数,偶数返回True,反之返回False
def isEven(x):
return x % 2 == 0
if __name__ == "__main__":
li = [1, 2, 3, 4]
newList = list(filter(isEven, li))
print(newList)
输出:
[2, 4]
分析:这里的isEven函数是一个功能函数,用来判断是否为偶数,再通过filter函数进行筛选,将li列表中不是偶数的元素筛选掉,左右输出的是只有偶数的序列。
sorted (iterable, *, key=None, reverse=False)
*
是一个特殊分隔符,后面的两个参数时命名关键字参数。
key
中可以传入一个函数,用来指定排序规则,即映射函数,是排序的灵魂所在。reverse
则是决定最后输出序列是递增还是递减序列,默认是递增,即reverse = False
。想要改成递减即reverse = True
即可。函数返回一个递增或递减序列。
函数说明:排序。
实例:
例2.5.1:
>>> li = ['Z', 'a', 'z', 'c', 'A']
>>> sorted(li)
['A', 'Z', 'a', 'c', 'z']
‘Z‘<‘a‘
,所以大写Z排在小写a之前。且默认情况下排序结果是递增序列。改进2.0,例2.5.2:
>>> li = ['Z', 'a', 'z', 'c', 'A']
>>> sorted(li)
['A', 'Z', 'a', 'c', 'z']
>>> sorted(li, key = str.lower)
['a', 'A', 'c', 'Z', 'z']
改进3.0,例2.5.3:
>>> li = ['Z', 'a', 'z', 'c', 'A']
>>> sorted(li)
['A', 'Z', 'a', 'c', 'z']
>>> sorted(li, key = str.lower)
['a', 'A', 'c', 'Z', 'z']
>>> sorted(li, key = str.lower, reverse = True)
['Z', 'z', 'c', 'a', 'A']
顾名思义:函数作为返回值的函数。相当于函数中嵌套一个函数,然后实现该函数后,并返回该函数。
将函数作为结果返回也是高阶函数的另一个特性。
例3.2.1:
#!/user/bin/python
#coding=utf-8
_author_ = "zjw"
def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum
if __name__ == "__main__":
f1 = lazy_sum(1, 2, 3, 4)
f2 = lazy_sum(5, 6, 7, 8)
print f1, f2
print f1(), f2()
输出:
<function sum at 0x0000000002F785F8> <function sum at 0x0000000002F78668>
10 26
分析:
f1()
和f2()
来得到。lazy_sum
中又定义了函数sum
,且内部函数sum
可以引用外部函数 lazy_sum
的参数和局部变量。当lazy_sum
返回函数sum
时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”。lambda
。例4.2.1:
>>> list(map(lambda x : 2 * x, [1, 2, 3, 4, 5]))
[2, 4, 6, 8, 10]
分析:其中map函数和list的转化已经比较熟悉了。那么来看一下这里的lambda
函数lambda x : 2 * x
,它就相当于一下的函数:
def f(x):
return 2 * x
其中lambda
函数中的关键字lambda
就是用来昭示匿名函数,冒号前面的x
表示要传入函数的参数,冒号后的2 * x
表示的就是return
的内容。
例4.2.2
>>> f = lambda x, y : x + y
>>> f(1, 2)
3
>>> f('a', 'b')
'ab'
分析:如该lambda
函数表达式所示,函数传入两个数据,中间用,
号隔开,并返回两个数据的和,当然和也可以是字符串的和。且在该例子中,我们将该匿名函数作为一个对象赋值给了变量f
,调用变量f
即可调用我们创建的匿名函数。该函数的原型应该如下:
def f(x, y):
return x + y
首先来写一个简单的函数:
def now():
print("这里是now函数,时间是2020年1月19日21:57:19。")
现在我们有了一个简单的now()
函数,当我们想在这个函数的前后加一些装饰,即给他加一些说明时,我们往往会在now函数里面动手脚,但是当我们想要在不动now函数本体的情况下进行一些修改时,我们就要用到装饰器了。
这种在代码运行期间动态增加功能的方式,称之为装饰器
。
实例1:两层嵌套decorator用法
例5.2.1:
#!/user/bin/python
#coding=utf-8
_author_ = "zjw"
#用作now()函数的装饰函数
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
print("现在执行的是wrapper函数")
return wrapper
@log
def now():
print("2020 1 19")
if __name__ == "__main__":
now()
输出:
现在执行的是wrapper函数
call now():
2020 1 19
分析:在调用now函数的时候,实际上我们先调用了@log
中的函数内容。Python就是通过@
语法,把decorator置于函数的定义处的,并在调用该函数的时候,实际上是执行了now = log(now)
。
之所以我们看到先执行了wrapper函数,是因为我们进入到log函数后,先跳过了wrapper函数,执行了print("现在执行的是wrapper函数")
,在返回函数wrapper的时候调用了wrapper函数,并输出了下面的内容。我们看到wrapper函数的参数是(*args, **kw)
,所以该函数可以接受任意参数的调用。
实例2:三层嵌套decorator用法
实例5.2.2:
#!/user/bin/python
#coding=utf-8
_author_ = "zjw"
#用作now()函数的装饰函数
def log(text):
def decorator(func):
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
print('我现在执行的是decorator函数')
return wrapper
print("我现在执行的还是log函数")
return decorator
@log('execute')
def now():
print("2020 1 19")
if __name__ == "__main__":
now()
输出:
我现在执行的还是log函数
我现在执行的是decorator函数
execute now():
2020 1 19
分析:3层decorator调用实际上效果是:now = log(‘execute‘)(now)
。首先我们看到执行的是log函数,因为log函数要传参进去,我们传了一个‘execute‘信息进去,首先我们跳过里面的两层嵌套循环来到了print("我现在执行的还是log函数")
语句,在要返回decorator函数时我们进入到decorator函数,其中的func参数就是now
函数了,这时我们又先跳过了wrapper函数执行了print(‘我现在执行的是decorator函数‘)
语句,在返回wrapper函数的时候进入到wrapper函数,执行了wrapper函数的print(‘%s %s():‘ % (text, func.__name__))
语句,并进入func函数,即执行了now函数中的内容,最后层层返回,先返回到decorator函数,再最后退出了log装饰器。
例6.2.1:这里以int()
函数为例,当我们需要转换大量的二进制字符串时,每次传入int(x, base = 2)
非常麻烦,这时可以用下面方法解决。
#!/user/bin/python
#coding=utf-8
_author_ = "zjw"
import functools
if __name__ == "__main__":
int2 = functools.partial(int, base = 2)
print(int2('101'))
输出:
5
分析:其中int2 = functools.partial(int, base = 2)
语句其实可以用下面的函数代替:
def int2(x, base = 2):
return int(x, base)
两个的实现方式不同,但是能用一行代码解决的我们坚决不用两行。但是呢这只是暂时固定住函数的base参数,如果我们更改base值,调用时也是会发生变化的,如下:
#!/user/bin/python
#coding=utf-8
_author_ = "zjw"
import functools
if __name__ == "__main__":
int2 = functools.partial(int, base = 2)
print(int2('101', base = 8))
此时输出的是65了,即八进制转为十进制。
functools.partial
来创建一个新的函数,来固定住原函数中的某些参数,实现新的通用的功能。且用该创建方法更加的简洁,实则就是’节约代码行数‘啦。原文:https://www.cnblogs.com/vanishzeng/p/12215986.html