01函数高级特性
-
切片
列表或字典的切片,通过下标取出数据,
L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']
r=[]
n=3
for i in range(n):
r.append(L[i])
r
['Michael', 'Sarah', 'Tracy']
-
迭代
如果给定一个列表或元组,可以我们通过for
循环来遍历这个列表或元型态型态组,这种遍历我们称为迭代(重复)。
for x, y in [(1, 1), (2, 4), (3, 9)]:
... print(x, y)
>>> list(range(1, 11))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
生成器:
在Python中,一边循环一边计算的机制取出数据,称为生成器:
著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:
1, 1, 2, 3, 5, 8, 13, 21, 34, ...
def fibl():
a,b=0,1
for i in range(5):
yield b
a,b=b,a+b
a=fibl()
#for i in a:
# print(i)
print(next(a)) #依次取值
print(next(a))
print(next(a))
print(next(a))
生成器中的send方法:
def test():
i=0
while i<5:
if i==0:
temp=yield i #第一次执行返回正常值,之后yield暂停返回None给temp,
else:
yield i
print(temp)
i+=1
t=test()
print(t.__next__())
print(t.__next__())
print(t.__next__())
t.send('hahahh')
迭代器:
可以直接作用于for 循环的对象统称为可迭代对象: Iterable ,
一类是集合数据类型,如list 、 tuple 、 dict 、 set 、 str 等;
一类是generator ,包括生成器和带yield 的generator function。
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator,但是,生成器是迭代器,把list
、dict
、str
等Iterable
变成Iterator要
使用iter()
函数
Python的for循环本质上就是通过不断调用next()函数实现的,例如:
for i in range(5):
print(i)
#等价:
# 首先获得Iterator对象:
it = iter([1, 2, 3, 4, 5])
# 循环:
while True:
try:
# 获得下一个值:
x = next(it)
except StopIteration:
# 遇到StopIteration就退出循环
break
例子:
list=[1,2,3,4]
it = iter(list) # 创建迭代器对象
for x in it:
print (x, end=" ")
执行以上程序,输出结果如下:
1 2 3 4
在调用生成器运行的过程中,每次遇到产量时函数会暂停并保存当前所有的运行信息,返回产率的值,并在下一次执行下一个next()方法时从当前位置继续运行。
调用一个生成器函数,返回的是一个迭代器对象。
import sys
def fibonacci(n): # 生成器函数 - 斐波那契
a, b, counter = 0, 1, 0
while True:
if (counter > n):
return
yield a
a, b = b, a + b
counter += 1
f = fibonacci(10) # f 是一个迭代器,由生成器返回生成
while True:
try:
print (next(f), end=" ")
except StopIteration:
sys.exit()
执行以上程序,输出结果如下:
0 1 1 2 3 5 8 13 21 34 55
函数和生成函数,普通函数调用直接返回结果,生成函数的“调用”实际返回一个可迭代对象:
杨辉三角:
def triangles():
L = [1]
while True:
yield L
L.append(0)
L = [L[i - 1] + L[i] for i in range(len(L))]
n=0
for t in triangles():
print(t)
n = n + 1
if n == 10:
break
结果:
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
[1, 6, 15, 20, 15, 6, 1]
[1, 7, 21, 35, 35, 21, 7, 1]
[1, 8, 28, 56, 70, 56, 28, 8, 1]
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
闭包函数:
1、定义在函数内部的函数
2、包含对外部作用域而非全局作用域的引用
特点:
1、自带作用域
2、延迟计算(取到内存地址,加括号执行)
#定义一个函数
def test(number):
#在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包
def test_in(number_in):
print("in test_in 函数, number_in is %d"%number_in)
return number+number_in
#其实这里返回的就是闭包的结果
return test_in
#给test函数赋值,这个20就是给参数number
ret = test(20)
#注意这里的100其实给参数number_in
print(ret(100))
#注意这里的200其实给参数number_in
print(ret(200))
闭包在多变量的情况下的应用,直线方程:y=kx+b 在k和b定义的情况下,通过改变x得出与的值。
def test(a,b):
def test_in(x):
print(a*x+b)
return test_in
line1 = test(1,1)
line1(0)
line2 = test(10,4)
line2(0)
line1(10)
装饰器:
就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。
1、开放封闭原则,对扩展是开房的,对修改是封闭的
2、装饰器:装饰器本质是可以任意调用对象,被装饰的对象也可以是任意可调用对象
功能:在不修改被装饰对象源代码以及调用方式的前提下,对其添加新功能
原则:
1、不修改源代码
2、不修改调用方式
目标:添加新功能
基本的装饰器的例子:
def w1(func):
def inner():
print("---正在进行装饰----")
if True:
func()
else:
print("没有装饰")
return inner
@w1 #f1 = w1(f1)
def f1():
print("---f1---")
@w1 #f2 = w1(f2)
def f2():
print("---f2---")
f1() #调用
f2()
结果:
---正在进行装饰----
---f1---
---正在进行装饰----
---f2---
def w1(func):
print("---正在装饰1----")
def inner():
print("---正在验证权限1----")
func() #指向w2的func
return inner
def w2(func):
print("---正在装饰2----")
def inner():
print("---正在验证权限2----")
func() #指向f1
return inner
#只要python解释器执行到了这个代码,那么就会自动的进行装饰,而不是等到调用的时候才装饰的
@w1 #f1=w1(f1) 再进行w1的装饰
@w2 #f1=w2(f1) 先进行这个
def f1():
print("---f1---")
#在调用f1之前,已经进行装饰了
f1()
#结果:
---正在装饰2----
---正在装饰1----
---正在验证权限1----
---正在验证权限2----
---f1---
通用版:
通用的装饰器,带参数返回值
def func(functionName):
def func_in(*args, **kwargs):
#print("-----记录日志-----")
ret = functionName(*args, **kwargs)
return ret
return func_in
@func
def test():
print("----test----")
return "haha"
@func
def test2():
print("----test2---")
@func
def test3(a):
print("-----test3--a=%d--"%a)
ret = test()
print("test return value is %s"%ret)
a = test2()
print("test2 return value is %s"%a)
test3(11)
#结果:
----test----
test return value is haha
----test2---
test2 return value is None
-----test3--a=11--
import time
import random
def timmer(func): # func = index
def wrapper():
start_time = time.time()
func()
stop_time = time.time()
print('run time is %s' %(stop_time - start_time))
print(wrapper)
return wrapper
@timmer #timmer(index)
def index():
time.sleep(random.randrange(1,2))
print('welcome to my index page !')
index() # index = timmer(index)
02高阶函数
- map/reduce()
第一个参数函数以参数序列中的每一个元素调用函数函数,返回包含每次函数函数返回值的新列表。
list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
#结果:
['1', '2', '3', '4', '5', '6', '7', '8', '9']
reduce() 函数会对参数序列中元素进行累积。
函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给reduce中的函数函数(有两个参数)先对集合中的第1,2个元素进行操作,得到的结果再与第三个数据用function函数运算,最后得到一个结果。
reduce(lambda X ,ÿ :X + Ý ,[ 1 ,2 ,3 ,4 ,5 ] )
#使用lambda匿名函数== 15 也可以直接用sum()
- filter() 过滤序列
filter()
的作用是从一个序列中筛出符合条件的元素。由于filter()
使用了惰性计算,所以只有在取filter()
查询查询查询查询结果的时候,才会真正筛选并每次返回下一个筛出的元素。
def _odd_iter():
n = 1
while True:
n = n + 2
yield n
def _not_divisible(n):
return lambda x:x%n>0 #返回除法的余数
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,end=' ')
else:
break
2 3 5 7 11 13 17 19 23 29 31 37 41。。。。。[Finished in 0.2s]
- sorted()排序算法:
排序也是在程序中经常用到的算法。无论使用冒泡排序还是快速排序,排序的核心是比较两个元素的大小。如果是数字,我们可以直接比较,但如果是字符串或者两个字典呢?直接比较数学上的大小是没有意义的,因此,比较的过程必须通过函数抽象出来。
by_name = lambda t: t[0]
by_score = lambda t: t[1]
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
L1 = sorted(L, key=by_name) #sorted()函数也是一个高阶函数,它还可以接收一个函数来实现自定义的排序
L2 = sorted(L, key=by_score, reverse = True)
print(L1)
print(L2)
结果:
[('Adam', 92), ('Bart', 66), ('Bob', 75), ('Lisa', 88)]
[('Adam', 92), ('Lisa', 88), ('Bob', 75), ('Bart', 66)]