1.函数名也是变量,其实就是一个指向函数的变量,比如:
>>> f=abs
>>> f(10)
10
>>> f(-10)
10
>>>
>>> abs=-10
>>> abs
-10
>>>
2.既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称为高阶函数。
一个简单的高阶函数:
>>> f=abs
>>> def abs(x,y,f):
... return f(x)+f(y)
...
>>> abs(-1,2,f)
3
3.map函数。map()接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。比如函数f(x)=x2,要把这个函数作用在一个list[1,2,3,4,5,6,7,8,9]上,就可以用map()实现如下:
代码实现:
>>> def f(x):
... return x*x
...
>>> r=map(f,[1,2,3,4,5,6,7,8,9])
>>> list(r)
[1, 4, 9, 16, 25, 36, 49, 64, 81]
>>>
把一个list的数字全转为字符:
>>> list(map(str,['aa',1]))
['aa', '1']
>>>
个人感觉,map函数就是用来把原来只能接受一个参数的函数变成可以接受一个数组的函数
4.reduce()函数:它把一个函数作用在一个序列[x1,x2,x3,...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
5.reduce()和map()的结合:
from functools import reduce
def char2num(s):
return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
def fn(x,y):
return x*10+y
reduce(fn,map(char2num,'13579'))
13579
初学python,觉得这段代码还真有点难以理解,下面是对代码的解释:
(1)return {}[]
这个return语句的意思是返回dict的value值,{}是dict,[]是key值,返回的就是这个key值的value值。
(2)觉得难以理解的是这句:reduce(fn,map(char2num,'13579'))
。首先是map将‘13579‘转成[1,3,5,7,9],然后就变成reduce(fn,[1,3,5,7,9]),然后就顺利成章啦。
6.还可以用lambda进一步简化:
from functools import reduce
def char2num(s):
return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
def str2int(s):
return reduce(lambda x, y: x * 10 + y, map(char2num, s))
lambda函数就是一个不需要return的函数
练习1
利用map()函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。输入:['adam', 'LISA', 'barT'],输出:['Adam', 'Lisa', 'Bart']:# -*- coding: utf-8 -*-
----
def normalize(name):
b=[]
b.append(name[0].upper())
for i in range(1,len(name)):
b.append(name[i].lower())
c="".join(b)
return c
----
测试:
L1 = ['adam', 'LISA', 'barT']
L2 = list(map(normalize, L1))
print(L2)
['Adam', 'Lisa', 'Bart']
另一个不用循环的方案:
参考博客2
L1 = ['adam', 'LISA', 'barT']
# -*- coding: utf-8 -*-
def normalize(name):
c=name[0].upper()+name[1:].lower()
return c
练习2
Python提供的sum()函数可以接受一个list并求和,请编写一个prod()函数,可以接受一个list并利用reduce()求积:# -*- coding: utf-8 -*-
from functools import reduce
def prod(L):
----
def fn(x,y):
return x*y
return reduce(fn,L)
----
print('3 * 5 * 7 * 9 =', prod([3, 5, 7, 9]))
3 * 5 * 7 * 9 = 945
练习3
利用map和reduce编写一个str2float函数,把字符串'123.456'转换成浮点数123.456:# -*- coding: utf-8 -*-
from functools import reduce
def str2float(s):
----
n=s.index('.')
def fn(x,y):
return x*10+y
L1=list(map(int,s[:n]))
L2=list(map(int,s[n+1:]))
return reduce(fn,L1)+reduce(fn,L2)/(10**len(L2))
----
print('str2float(\'123.456\') =', str2float('123.456'))
7.filter函数。该函数用于过滤序列,就是去掉真的,留下假的, (1)比如在一个list中删掉奇数:
def is_even(n):
return n%2==0
list(filter(is_even,[1,2,3,4,5,6,7]))
[2, 4, 6]
(2)把一个序列中的空字符串删掉:
def not_empty(s):
return s and s.strip()
list(filter(not_empty,['',None,'diu ',' h ha']))
['diu ', ' h ha']
这里插播一下str.strip()的用法:
Python strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。语法是str.strip([chars]);
如果括号为空,那么就是默认为空格或换行符。另外,只由空格组成的字符串不等于None
def judge():
return ' '==None
judge()
False
(3)用filter打印100以内的素数
#构造一个从3开始的奇数序列
def _odd_iter():
n=1
while True:
n=n+2
yield n
#定义一个筛选函数:
def _not_divisible(n):
return lambda x:x%n>0
#函数返回一个匿名函数,赋值给p,p是一个函数,函数带括号调用,比如:
# p = _not_divisible(10)
# print p(5)
#最后定义一个生成器,不断返回下一个素数:
def primes():
yield 2
it=_odd_iter() #初始序列
while True:
n=next(it)#返回序列的第一个数
yield n
it=filter(_not_divisible(n),it)#构造新序列
#打印1000以内的素数:
for n in primes():
if n<1000:
print(n)
else:
break
练习
回数是指从左向右读和从右向左读都是一样的数,例如12321,909。请利用filter()滤掉非回数:# -*- coding: utf-8 -*-
def is_palindrome(n):
b=str(n)
i=0
lens=len(b)
flag=True
for i in range(0,lens//2):
if b[i]!=b[len(b)-1-i]:
flag=False
break
return flag
output = filter(is_palindrome, range(1, 1000))
print(list(output))
# 测试:
output = filter(is_palindrome, range(1, 1000))
print(list(output))
运行结果:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191, 202, 212, 222, 232, 242, 252, 262, 272, 282, 292, 303, 313, 323, 333, 343, 353, 363, 373, 383, 393, 404, 414, 424, 434, 444, 454, 464, 474, 484, 494, 505, 515, 525, 535, 545, 555, 565, 575, 585, 595, 606, 616, 626, 636, 646, 656, 666, 676, 686, 696, 707, 717, 727, 737, 747, 757, 767, 777, 787, 797, 808, 818, 828, 838, 848, 858, 868, 878, 888, 898, 909, 919, 929, 939, 949, 959, 969, 979, 989, 999]
这是一行代码解决的:
def is_palindrome(n):
return n==int(str(n)[::-1])
这里str(n)[::-1]是这样的:str[开始:结束:步长],步长等于-1时相当于倒序排列.步长为正数时相当于隔一步取一个数,比如:
def is_palindrome(n):
8.sorted函数:这个函数可以直接接收一个list对其进行排序,也可以接收一个key函数来自定义排序,比如按绝对值大小排序:
>>> sorted([36, 5, -12, 9, -21], key=abs)
[5, 9, -12, -21, 36]
甚至还可以接收第三个参数reverse,例如要按ASCII对字符串进行从大到小的排序,并且忽略大小写:
>>> sorted([36, 5, -12, 9, -21], key=abs)
[5, 9, -12, -21, 36]
练习
假设我们用一组tuple表示学生名字和成绩: L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)] 请用sorted()对上述列表分别按名字排序:# -*- coding: utf-8 -*-
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
def by_name(t):
return t[0]
L2 = sorted(L, key=by_name)
print(L2)
[('Adam', 92), ('Bart', 66), ('Bob', 75), ('Lisa', 88)]
再按成绩从高到低排序:
# -*- coding: utf-8 -*-
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
def by_score(t):
return t[1]
L2 =sorted(L,key=by_score)
print(L2)
[('Bart', 66), ('Bob', 75), ('Lisa', 88), ('Adam', 92)]
9.返回函数:
来看一个函数:
def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum
f=lazy_sum(1,3,5,7,9)
f#在这里f只是一个求和函数
<function __main__.lazy_sum.<locals>.sum()>
f()#这里才真正计算求和的结果,在变量的后面加了一个括号,执行内函数
25
在这个函数中,在外部函数中定义了内部函数,并且内部函数可以引用外部函数的参数和局部变量,当外部函数返回内部函数时,相关参数和变量都保存在返回的函数中,这种程序结构称为闭包。
10.返回一个函数时牢记该函数并未执行,返回函数中不要引用任何可能会变化的变量
11.匿名函数:一个示例如下:
lambda x: x*x
关键字lambda表示匿名函数,冒号前面的x表示函数参数
(1)匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果
(2)匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数
>>> f =lambda x:x*x
>>> f(5)
25
>>>
12.装饰器:在代码运行期间动态增加功能的方式,称为装饰器(decorator)