1.几道练习题
# 2、写函数,接收n个数字,求这些参数数字的和。 # def func(*args): # sum1 = 0 # for i in args: # sum1 += i # return sum1 # # print(func(1,2,3,4)) # 3、读代码,回答:代码中,打印出来的值a,b,c分别是什么?为什么? # a=10 # b=20 # def test5(a,b): # print(a, b) # c = test5(b, a) # print(c) # # 4、读代码,回答:代码中,打印出来的值a,b,c分别是什么?为什么? # a = 10 # b = 20 # def test5(a, b): # a = 3 # b = 5 # # print(a, b) # c = test5(b, a) # print(c) #2、写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者。 # def func(l): # return l[::2] # print(func([1,2,3,4,5])) # 3、写函数,判断用户传入的值(字符串、列表、元组)长度是否大于5。 # def func(x): # return len(x)>5 # # print(func('sdfdg')) # 4、写函数,检查传入列表的长度,如果大于2, # 那么仅保留前两个长度的内容,并将新内容返回给调用者。 # def func(l): # if len(l) >2: # return l[:2] # print(func([1,2,3,4])) # 5、写函数,计算传入字符串中【数字】、【字母】、【空格】 以及 【其他】的个数,并返回结果。 # def func(s): # num = 0 # alpha = 0 # space = 0 # other = 0 # #dic = {'num':num,'alpha':alpha,'space':space,'other':other} # for i in s: # if i.isdigit(): # num += 1 # elif i.isalpha(): # alpha += 1 # # elif i.isspace(): # elif i == ' ':#此处判断字符是否是空格只能用' ',因为isspace 包括特殊字符 # space += 1 # else: # other += 1 # dic = {'num': num, 'alpha': alpha, 'space': space, 'other': other} # return dic # # print(func('dkfsjf 123+-')) # # def func(s): #'skghfoiw8qpeuqkd' # dic = {'num':0,'alpha':0,'space':0,'other':0} # for i in s: # if i.isdigit(): # dic['num']+=1 # elif i.isalpha(): # dic['alpha'] += 1 # elif i.isspace(): # dic['space'] += 1 # else: # dic['other'] += 1 # return dic # print(func('+0-0skahe817jashf wet1')) # 6、写函数,检查用户传入的对象(字符串、列表、元组) # 的每一个元素是否含有空内容,并返回结果。 # def func(x): # if type(x) is str and x: #参数是字符串 # for i in x: # if i == ' ': # return True # elif x and type(x) is list or type(x) is tuple: #参数是列表或者元组 # for i in x: # if not i: # return True # elif not x: # return True # # print(func([])) #7、写函数,检查传入字典的每一个value的长度,如果大于2, # 那么仅保留前两个长度的内容,并将新内容返回给调用者。 # dic = {"k1": "v1v1", "k2": [11,22,33,44]} # PS:字典中的value只能是字符串或列表 # def func(s): # for i in s: # if len(s[i])>2: # s[i] = s[i][:2] # return s # dic = {'name':'123','age':'23'} # print(func(dic)) # def func(dic): # for k in dic: # if len(dic[k]) > 2: # dic[k] = dic[k][:2] # return dic # dic = {"k1": "v1v1", "k2": [11,22,33,44]} # print(func(dic)) # 8、写函数,接收两个数字参数,返回比较大的那个数字。 # def func(a,b): # return a if a>b else b#三元运算符 # print(func(1,2)) # # print(max(1,21,3)) # def func(a,b): # if a>b: # return a # else: # return b # print(func(1,5)) # def func(a,b): # return a if a > b else b # print(func(5,1)) # 三元运算 # a = 1 # b = 5 # c = a if a>b else b #三元运算 # print(c) # 变量 = 条件返回True的结果 if 条件 else 条件返回False的结果 #必须要有结果 #必须要有if和else #只能是简单的情况 # 9、写函数,用户传入修改的文件名,与要修改的内容, # 执行函数,完成整个文件的批量修改操作(进阶)。 def func(filename,old,new): with open(filename,mode = 'r',encoding = 'utf-8') as f,open('%s.bak'%filename,'w',encoding='utf-8') as f2: for line in f: if old in line: line.replace(old,new) f2.write(line) import os os.remove(filename) os.rename('%s.bak'%filename,filename)
2.装饰器
装饰器的本质:一个闭包函数
装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展
开放封闭原则
1.对扩展是开放的
为什么要对扩展开放呢?
我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。
2.对修改是封闭的
为什么要对修改封闭呢?
就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。
装饰器完美的遵循了这个开放封闭原则。
# import time # print(time.time()) # time.sleep(3) # print(1) # import time # def timer(func): # def inner(): # start = time.time() # func() # time.sleep(2) # print(time.time()-start) # return inner # def func1(): # print('装饰器') # func1 = timer(func1) # func1() def timer(func): def inner(): start = time.time() func() time.sleep(2) print(time.time()-start) return inner @timer # ==>func1 = timer(func1) def func1(): print('装饰器') func1()
3.装饰带参数的函数
import time # def timer(func): # def inner(*args,**kwargs): # start = time.time() # f = func(*args,**kwargs) # print(time.time()-start) # return f # return inner # @timer # ==>func1 = timer(func1) def func1(a): print(a) # @timer def func2(a,b): #fdffdd print(a,b) return 100 func1(2) print(func2(1,3))
4.迭代器
迭代器遵循迭代器协议:必须拥有__iter__方法和__next__方法。
# for i in 1234: # print(i)#TypeError: 'int' object is not iterable #判断是否是可迭代的对象方法 isinstance # from collections import Iterable # l = [1,2,3,4] # t = (1,2,3,4) # d = {1:2,3:4} # s = {1,2,3,4} # print(isinstance(l,Iterable)) # print(isinstance(t,Iterable)) # print(isinstance(d,Iterable)) # print(isinstance(s,Iterable)) #dir([1,2].__iter__())是列表迭代器中实现的所有方法,dir([1,2])是列表中实现的所有方法,都是以列表的形式返回给我们的,为了看的更清楚,我们分别把他们转换成集合, #然后取差集。 # print(dir([1,2])) # print([1,2].__iter__())#iterator,这里给我们标出来了,是一个计算机中的专属名词,叫做迭代器。 # print(dir([1,2].__iter__())) # print(set(dir([1,2]))-set(dir([1,2].__iter__()))) # print(set(dir([1,2].__iter__()))-set(dir([1,2]))) # # iter_1 = [3,4,3].__iter__() # # print(iter_1.__next__()) # # print(iter_1.__next__()) # # print(iter_1.__setstate__(2))#根据索引值指定从哪里开始迭代 # print(iter_1.__next__())#一个一个的取值 # print(iter_1.__length_hint__())#获取迭代器中元素的长度 #异常处理机制 l = [1,2,3,4] iter_1 = l.__iter__() while 1: try: item = iter_1.__next__() print(item) except StopIteration: break
5.生成器
我们知道的迭代器有两种:一种是调用方法直接返回的,一种是可迭代对象通过执行iter方法得到的,迭代器有的好处是可以节省内存。
如果在某些情况下,我们也需要节省内存,就只能自己写。我们自己写的这个能实现迭代器功能的东西就叫生成器。
Python中提供的生成器:
1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行
2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表
生成器Generator:
本质:迭代器(所以自带了__iter__方法和__next__方法,不需要我们去实现)
特点:惰性运算,开发者自定义
生成器函数
一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。
# print('__next__' in dir(range(12))) #查看'__next__'是不是在range()方法执行之后内部是否有__next__ # print('__iter__' in dir(range(12))) #查看'__next__'是不是在range()方法执行之后内部是否有__next__ # # from collections import Iterator # print(isinstance(range(100000000),Iterator)) #验证range执行之后得到的结果不是一个迭代器 # # # # import time # def genrator_fun(): # a = 1 # print('定义a') # yield a # b = 2 # print('定义b') # yield b # # g1 = genrator_fun() # # print(g1) # print(next(g1)) # g1.__next__() def produce(): ''' 生产衣服''' for i in range(200): yield "生产了第%s件衣服"%i product = produce() print(product.__next__()) print(product.__next__()) num = 0 for i in product: print(i) num += 1 if num == 5: break
6.生成器的send
#send 获取下一个值的效果和next基本一致 #只是在获取下一个值的时候,给上一yield的位置传递一个数据 #使用send的注意事项 # 第一次使用生成器的时候 是用next获取下一个值 # 最后一个yield不能接受外部的值
def generator(): print(123) content = yield 1 print('----',content) print(456) yield 2 g = generator() ret = g.__next__() print('ss',ret) ret = g.__next__() # ret = g.send('hello') print('gg',ret)