python操作数据对象方法和高阶函数
高级特性
对序列切片
序列对象[start : end(不包括) : step],序列包括列表list、元组tuple、字符串str
l = [1,2,3,4] # list
t = ('1','2','3','4') # tuple
s = "today" #str
l[:2] # [1, 2]
l[0::2] # [1, 3]
t[:] # ('1', '2', '3', '4')
t[-2:] # ('3', '4')
s[1:3] # 'od'
对迭代对象Iterable进行迭代
常见迭代对象是列表list、元组tuple、字典dict、字符串str,集合set、生成器对象generator、生成器函数generator function ,可以通过 isinstance(迭代对象, Iterable)判断是否迭代对象。
from collections.abc import Iterable
isinstance('hellow2024', Iterable) # True
d = {"a":90,"b":80,'c':70}
t= (1,2,3)
print("————字典默认迭代key————")
for key in d:
print(key)
print("————字典迭代键-值—————")
for key,value in d.items():
print(key+":"+str(value))
print("—————迭代元组,其它迭代对象同理————")
for x in t:
print(x)
print("—————迭代元组及其下标,其它序列同理————")
for i,x in enumerate(t):
print(i,' ',x)
'''
————字典默认迭代key————
a
b
c
————字典迭代键-值—————
a:90
b:80
c:70
—————迭代元组,其它同理————
1
2
3
—————迭代元组及其下标,其它同理————
0 1
1 2
2 3
'''
列表推导式
List = range(10)
newList1 = [2*x+1 for x in List]
# 相当于
newList1 = []
for x in List:
newList1.append(2*x+1)
newList2 = [x for x in List if x>=5 and x<15]
# 相当于
newList2 = []
for x in List:
if x>=5 and x<15:
newList2.append(x)
'''
还可以不断的嵌套for 和if 但是要明确这些for和if只是为了
确定能取到符合条件的List里的值,所以else不能出现
'''
# 还可以有其它迭代对象
newList3 = [k + ":"+ str(v) for k,v in {"a":90,"b":80,'c':70}.items()]
newList3
生成器generator
生成器也是一个可迭代对象,所生成的是生成列表的规律或某种步骤,这样我们想用时再生成,节约空间。与列表生成式区别在于使用圆括号‘()’显示。
另外,生成器generator所生成元素数量长度是未知的,实现惰性求值(即只在需要时才计算结果)。因为只能通过在通过next()去获取下一个值时,该值在内存上是不存在的。
可以通过iter( some_Object)将例如列表对象转换为生成器对象genarator。
g = (x * x for x in range(10))
g
# <generator object <genexpr> at 0x000002784EE05A48>
g = (x+2 for x in range(10))
g
# 使用next()获取该迭代器对象下一个元素
for i in range(10):
print(next(g))
# 直接利用它是迭代对象的特性
for x in g:
print(x)
生成器函数
'''
面对较复杂的规则,可以定义生成器函数
使用yield关键字将生成器值返回(每一次迭代取数或使用next()都是运行到yield就中断返回该值 ),
下一次就接着上次yeid value语句下面继续执行,例如a,b = b,a+b。
当所有元素都迭代完,若再一次调用next()便抛出StopIteration异常并返回return值。
'''
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
'''
每调用一次生成器函数,其返回的生成器对象是独立的
'''
函数进阶
map函数
'''map(f,Iterable),,-对迭代对象每一个元素作用f函数求得新值并返回一个生成器对象'''
g = map(abs,(-1,-2,-99,8))
for i in g:
print(i)
# abs是绝对值函数对象,abs和普通变量等同,只不过其指向了求绝对值函数对象
reduce函数
from functools import reduce
'''
参数1:f是一个接受两个参数的函数
参数2:是一个数值序列
reduce(f,[1,2,3]) => f(f(1,2),3)
'''
def f(x,y):
return (x+y)
sumv = reduce(f,[1,2,3,4,5])
sumv
filter函数
'''
filter接受两个参数
参数1:返回值为布尔类型的函数对象,其作用于参数2每一个元素并将返回值为True的元素生成新迭代对象
参数2:一个可迭代对象
'''
# 生成以3开头的奇数数列,没有考虑2和去除2的倍数
def odd_iter():
n = 3
yield n
while True:
n = n + 2
yield n
# 返回值是一个函数对象,该函数返回值为布尔值,判断传入x是否是n的倍数,那些数自然不可能是素数
def not_divisiable(n):
def process(x):
return x%n !=0
return process
# 生成素数数列
def prime_printer():
yield 2 # 把没考虑的2加上
it = odd_iter() # 生成奇数列迭代对象
# 可以一直迭代
while True:
n = next(it)
yield n
# 将原数列中第一位(为素数)的倍数去除并构成新数列
it = filter(not_divisiable(n),it)
piter = prime_printer()
# 希望迭代出100以内素数
for prime in piter:
if prime<100:
print(prime)
else:
break
sorted函数
'''
sorted(可迭代对象iterable,key=f可缺省,reverse=False可缺省),返回
f函数制定排序的标准
'''
def sortByAge(d):
return d['age']
sorted([{'name':'fw','age':22},{'name':'yy','age':15},{'name':'nn','age':13}],key=sortByAge)
'''
[{'name': 'nn', 'age': 13},
{'name': 'yy', 'age': 15},
{'name': 'fw', 'age': 22}]
'''
g = (x for x in range(10))
sorted(g,reverse=True)
'''
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
'''
将函数作为返回值使用闭包
在函数嵌套的情况下,内部函数使用外部函数中的变量,且外部函数返回了内部函数对象,这个内部函数称之为闭包。
内部函数虽然能调用外部函变量值,但不能直接改变其值,需要使用nonlocal x声明x变量不是本内部函数局部变量。
不要引用外层函数中的循环中的变量值,因为,内层函数不会立即求值,等到调用时,循环中被引用的值可能已经改变。
def f1():
lf=[]
for i in range(1,4):
def f3():
return i
lf.append(f3)
return lf
print(f1())
f31,f32,f33 = f1()
print(f31(),' ',f32(),' ',f33())# 都引用了循环最终变量3
'''
[<function f1.<locals>.f3 at 0x0000019572B47EE8>, <function f1.<locals>.f3 at 0x0000019572B47AF8>, <function f1.<locals>.f3 at 0x0000019572B47D38>]
3 3 3
'''
除非多嵌套一个函数并将循环中的值绑定在多增加的介于内层和外层函数中间的函数参数中
def f1():
lf=[]
def f2(i):
def f3():
return i
return f3
for i in range(1,4):
lf.append(f2(i))
return lf
print(f1())
f31,f32,f33 = f1()
print(f31(),' ',f32(),' ',f33())# 1 2 3
匿名函数lambda
'''
使用lambda 语句定义匿名函数
冒号前表示参数
只能有一个表达式,返回表达式结果
没有return语句
lambda 参数1,参数2、参数3等:一个表达式语句
'''
x = lambda a,b:a+b
x(1,2)
d =map(lambda x:x+1,[1,2,3])
list(d) # 将iterator类型转换为list
# 也可以直接用for迭代
装饰器
装饰器能在不改变某一函数的定义代码情况下,通过定义另一实现额外功能的函数并通过’@语法‘让原函数函数名指向这''另一函数‘来实现额外功能。
1.无参数的装饰器
import functools
# 在pTime()函数执行功能基础上额外输出一个日志,不改变pTime
def log(f):
@functools.wraps(f)# 将f指向的函数内置属性如__name__复制到wrapper函数
def wrapper(*args,**kw):#*args,**kw可以接受任何参数
print("log:执行额外功能在函数%s",f.__name__)#__name__属性为函数名,内置不用自己定义
return f(*args,**kw)
return wrapper
@log #用log装饰pTime
def pTime():
print("2024.9.3 22:23")
pTime()
'''
输出:
log:执行额外功能在函数%s pTime
2024.9.3 22:23
'''
'''
执行过程:
step1: pTime = log(pTime) # 调用log,此时pTime指向log的返回值wrapper,
step2: pTime() # 调用pTime,相当于调用wrapper,并提供return f(*a,**k)调用原来的pTime功能
'''
2.带参数的装饰器
import functools
# 在pTime()函数执行功能基础上额外输出一个日志,不改变pTime
def log(some_arg):
def decorator(f):
@functools.wraps(f)# 将f指向的函数内置属性如__name__复制到wrapper函数
def wrapper(*args,**kw):#*args,**kw可以接受任何参数
print("log:%s"%some_arg)#__name__属性为函数名,内置不用自己定义
return f(*args,**kw)
return wrapper
return decorator
@log("开始打印日志...") #用log装饰pTime,有参数,实际上的装饰器是内部的decorator函数
def pTime():
print("2024.9.3 22:23")
pTime()
'''
输出:
log:开始打印日志...
2024.9.3 22:23
执行过程:
my_decorator = log("开始打印日志...") # 调用log,返回内部decorator函数对象
pTime = my_decorator(pTime) # 调用decorator函数,此时pTime指向decorator的返回值wrapper,
pTime() # 调用pTime,相当于调用wrapper,并提供return f(*a,**k)调用原来的pTime功能
'''
partial()给已有函数设默认值返回新函数
import functools
# functools.partial(fun_object,*arg,**kw)
x1 =int('123')
print(x1)
x2 = int('123',base=8)
print(x2)
int2 = functools.partial(int,base=8) # kw = {base:8};int('123',**kw)
x3 = int2('123')
print(x3)
参考:
函数式编程 - Python教程 - 廖雪峰的官方网站 (liaoxuefeng.com)