一、切片
在对数据进行操作时,需要对list,tuple或str取出部分元素
l1 = ['Shanghai','Beijing','Shenzheng','Guangzhou','Hangzhou']
'''在l1中取出前4个城市'''
l2 = [l1[0],l1[1],l2[2],l3[3]]
对于一个长列表,需要取出100个元素
l3 = [1,2,3,4......n] # n > 1000
'''从l3中取出前100个元素'''
l4 = l3[0:100] # l4=[1,2,3,4,....100]
上述代码中的 l3[0:100]即是切片,从l3索引0开始,一直取到索引100,但不包含索引100,即取索引0,1,2,3……99对应的元素(前包含后不包含)
当第一个索引为0的时候可简写
l4 = l3[:100] # 第一个索引为0时可省略实现简写
从元素第2个开始,取出3个元素
l5 = l3[1:4] # l5=[l3[1],l3[2],l3[3]]
注意索引的前包含后不包含,所以取l3[1], l3[2], l3[3]
当然Python也支持倒数取元素
l5 = ['a','b','c','d','e']
l6 = l5[-1] # 取l5倒数第一个元素,即'e'
l7 = l5[-3:-1] # 取l5倒数第3个,倒数第2个元素,即l5[-3],l5[-2]
注:
通过切片倒数取元素时,同样遵循前包含后不包含;
倒数第一个元素索引从 -1 开始
对于一个长数列,通过切片可轻松取出任意一段数列
l8 = list(range(100)) # l8 = [0,1,2,3.....98,99]
l9 = l8[:10] # 取前10个数 [0,1,2,3,4,5,6,7,8,9]
l10 = l8[-10:] # 取后10个数 [90,91,92....99]
l11 = l8[5:10] # 取索引为5-9的元素
通过切片间隔取元素
l12 = [1,2,3,4,5,6,7,8,9,10]
l13 = l12[0:10:2]
# 对列表l12按索引间隔为2取元素,即l13=[l12[0],l12[2],l12[4],l12[6],l12[8]]
# 1,3,5,7,9
任务:l8 = list(range(100)) ,通过切片形式,取出l8中所有奇数
l = list(range(100))
l2 = l[1::2]
print(l2)
任务:尝试一下l14 = l8[ : ]
tuple也是一种特殊的list,唯一区别就是tuple不可变,因此tuple也可以进行切片,切片结果仍是tuple
t1 = (1,2,3,4,5)
t2 = t1[0:3] # tuple也可进行切片
字符串进行切片
s1 = 'abcdefg'
s2 = s1[0:4] # str也能进行切片
字符串第一个元素就是一个字符,切片结果仍是字符串
任务:给定一个字符串,该字符串首尾都包含空格,通过切片的形式,去除该字符串首尾空格
s3 = ' 测试字符串.....n '
'''s3是一个字符串,首发包含空格,通过切片的形式,生成一个新字符串s4,去除s3的首尾空格'''
二、迭代(Iteration)
通过for循环来遍历list或tuple等可迭代对象,Python中通过 for…in 来完成迭代
dic = {'k_1':'v_1','k_2':'v_2','k_3':'v_3'}
for i in dic: # 字典也可迭代,但输出的是key
print (i) # 输出:k_1 k_2 k_3
迭代字典对象时,默认输出的是字典的所有 key
如果要迭代字典中的value,可通过 for i in dic.values( ),如果要同时迭代key和value,可以用for k, v in dic.items( )
for i in dic.values(): # 迭代输出字典的value
print(i) # v_1 v_2 v_3
for k, v in d.items(): # 同时迭代key,value
print(f'{k}:{v}') # k_1:v_1 k_2:v_2 k_3:v_3
迭代字符串
s = "测试字符串"
for i in s: # 迭代字符串
print(i)
任务:通过迭代,查找list [1,8,4,7,5,3,2]的最大数
三、列表生成式
L = [表达式 for 变量 in 可迭代对象 ]
即:变量从可迭代对象中获取元素作用到表达式中
遍历列表 [1,2,3,4,5,6,7] 根据公式 2x+1,生成一个新的列表
l1 = [1,2,3,4,5,6,7]
l2 = []
for x in l1:
s = 2*x+1
l2.append(s)
# l2列表[3, 5, 7, 9, 11, 13, 15]
运用列表生成式简化上述代码
l2 = [2*x+1 for x in l1] #l2列表[3, 5, 7, 9, 11, 13, 15]
列表生成式中for循环后面可以加if判断进行筛选
l3 = [2*x+1 for x in l1 if x % 2 ==0] # 结果[5, 9, 13]
上述代码只有满足if 条件后的元素才会参加 2*x+1 运算,注意:列表生成式中if作为筛选条件,后面不能跟else
列表生成式中for循环后面可以再嵌套for循环
l4 = [x+y for x in '123' for y in 'abc']
# ['1a','1b','1c','2a','2b','2c','3a','3b','3c']
任务:根据l4列表生成式逻辑,请定义一个函数,使用嵌套的for循环实现上述代码功能
任务:根据下面代码,改写成列表生成式
l5 = [1,2,3,4,5,6]
l6 = []
for i in l5:
if i >= 3:
s = i*i + 1
l6.append(s)
四、生成器(generator)
列表对象对内存的占用,决定于其列表中元素个数,如果上百万个元素的列表不仅会占用很大的内部空间,而且其元素利用率不高将会造成很大的资源浪费,所以生成器,就是按照某种算法推算列表元素,通过循环能不断推断下一个元素,而不必创建整个list,来节省空间,即边循环边计算。
创建一个生成器
1.在列表生成式的基础上,把[ ]改成( ),就生成了一个generator
l = [x for x in range(10)]
print(type(l)) # <class 'list'>
l_g = (x for x in range(10))
print(type(l_g)) # <class 'generator'>
生成器可通过next( )函数来一个一个实现打印元素
next(l_g) # 0
next(l_g) # 1
next(l_g) # 2
next(l_g) # 3
当next(l_g) 没有更多元素时会抛出StopIteration
因为 generator 是可迭代对象,可使用for循环迭代
for i in l_g: # l_g是生成器也是迭代器
print(i)
2.在函数中通过 yield 来定义一个 generator
在Python程序中函数一般是顺序执行,遇到 return 语句返回结果并结束或执行到函数最后一句后结束运行,但在作为 generator 的函数,每次调用 next( ) 执行时,遇到 yield 就返回,当再次执行时是从上次返回的 yield 语句处继续执行
def new_generator():
print('执行第一次调用')
yield ('第一次返回1')
print('执行第二次调用')
yield '第二次返回2'
print('执行第三次调用')
yield '第三次返回3’
n = new_generator()
print(next(n)) # 执行第一次调用
第一次返回1
print(next(n)) # 执行第二次调用
第二次返回2
print(next(n)) # 执行第三次调用
第三次返回3
print(type(n)) # <class 'generator'>
for i in n: # 通过 for 循环迭代 new_generator
print(i)
'''
执行第一次调用
第一次返回1
执行第二次调用
第二次返回2
执行第三次调用
第三次返回3
'''
五、迭代器(Iterator)
可直接通过for循环的数据类型有:
1.集合类数据类型:list, tuple, dict, set, str
2.generator 生成器
所有可通过for循环迭代的可称为可迭代对象(Iterable)
迭代器:可以被next( )函数不断调用并返回下一个值的对象(Iterator)
问题:
1、迭代对象都是迭代器(True or False)?F
2、迭代器都是迭代对象(Ture or False)?T
3、生成器属于迭代器 ( Ture or False)?T
4、list, dict, str 是迭代器(True or False) ?F
生成器都是Iterator,但list、dict、str虽然是Iterable,却不是Iterator
Iteration/Iterable/Iterator?
iter( )函数可把Iterable 变成 Iterator
l = [1,2,3,4,5]
next(l) # TypeError: 'list' object is not an iterator
l_t = iter(l) # 通过iter()函数把list变成一个Iterator
print(next(l_t))
print(next(l_t))
print(next(l_t))
总结:
1、凡是可用for循环的都是可迭代对象Iterable;
2、凡是可用next( )函数返回下一值的都是迭代器Iterator;
3、生成器是通过某种算法推算,边循环边计算的机制,可以通过next( )函数不断返回下一值
因此,生成器也是一种迭代器;
六、装饰器
前提概念一:
闭包:在函数中再嵌套一个函数,并且引用外部函数的变量,这就是一个闭包了
def outer(x):
def inner(y):
return x + y
return inner
print(outer(6)(5))
函数中可定义函数
def func_1():
print("正在调用func_1")
def func_1_1():
return "正在调用func_1_1"
def func_1_2():
return "正在调用func_1_2"
print(func_1_1())
print(func_1_2())
print("函数func_1调用结束")
#
正在调用func_1
正在调用func_1_1
正在调用func_1_2
函数func_1调用结束
函数中定义的函数,只能在func_1函数内调用
前提概念二:
函数中返回函数
def func_1():
print("正在调用func_1")
def func_1_1():
return "正在调用func_1_1"
print("函数func_1调用结束")
return func_1_1
a = func_1() #正在调用func_1
函数func_1调用结束
print(a) # <function func_1.<locals>.func_1_1 at 0x000001B92BE3DAF0>
print(a()) # 正在调用func_1_1
问题:为什么 print(a) 与 print(a( ))不一样?
前提概念三:
赋值与调用
def func_2():
print("函数func_2被调用")
a = func_2
print(a) # <function func_2 at 0x00000219AAD8F040>
b = func_2() # 函数func_2被调用
c = a() # 函数func_2被调用
从上述代码可知,当 a = func_2 时,是把func_2函数对象内存地址赋值给变量a,并不会执行func_2这个函数中的代码;当 b = func_2( )时,函数func_2( )会被调用,加上()会运行这个函数中的代码
装饰器:
在Python中,可以把函数A作为参数传入另一个函数B,从而实现在不改变函数A原有代码的基础上对函数A增加新功能
def func_A():
print("A函数本身的功能")
def func_B(func):
print("执行func_B开始")
def func_b():
print("func_b执行传入函数前做一些事情")
func()
print("func_b执行传入函数后做一些事情")
print("准备返回func_b")
return func_b
b = func_B(func_A) # func_B()执行返回一个 func_b 内嵌函数对象给func_A调用
'''
执行func_B开始
准备返回func_b
func_b执行传入函数前做一些事情
A函数本身的功能
func_b执行传入函数后做一些事情
'''
上述代码func_B函数就是一个装饰器函数,但需要调用func_B函数来实现对func_A函数的功能拓展,
通过@符号装饰func_A函数,可实现直接调用func_A函数来达成装饰器的目的
@func_B
def func_A():
print("A函数本身的功能")
func_A()
'''
执行结果:
执行func_B开始
准备返回func_b
func_b执行传入函数前做一些事情
A函数本身的功能
func_b执行传入函数后做一些事情
'''
被装饰的A函数有单个参数
def func_B(func):
def func_b(x):
return 2*func(x)
return func_b
@func_B
def func_A(x):
return int(x)+1
if __name__ == "__main__":
a = func_A(2)
print(a)
print(func_A.__name__) # 结果为func_b,即func_A被装饰后指向了func_b
被装饰的A函数有多个参数
def func_B(func):
def func_b(*args,**kwargs):
return 2*func(*args,**kwargs)
return func_b
@func_B
def func_A(x,y):
return int(x)+int(y)
if __name__ == "__main__":
a = func_A(2,3)
print(a)