一、知识储备
1. *args,**kwargs
def index(name,age): print(name,age) def wrapper(*args,**kwargs): #args=(1,2,2,3,4,4,5),kwargs={'x':1,'y':2} index(*args,**kwargs) #index(1,2,2,3,4,4,5,y=2,x=1) wrapper('egon',age=18)
2. 函数对象:函数可被当做数据传递
- 函数可以当做参数传给另外一个函数 - 一个函数的返回值也可以是一个函数(打破函数的层级限制) def f1(): def f2(): print('f2') return f2 f=f1() f()
3. 名称空间与作用域
名称空间 - 分三种 内置名称空间:python解释器启动则生效 全局名称空间:执行python文件时生效 局部名称空间:调用函数时,临时生效,函调用结束则失效 - 加载顺序:先内置,再全局,最后有可能产生局部 - 查找名字的顺序:先局部,再全局,最后内置 作用: - 分两种 全局作用域:全局存活,全局有效 局部作用域:临时存活,局部有效 强调:作用关系在函数定义阶段就已经固定,与调用位置无关
二、装饰器
1、闭包函数
闭包函数定义:定义在函数内部的函数,特点是:包含对外部作用域而不是对全局作用域名字的引用,该函数就称之为闭包函数
# x=1 # def outter(): # x=2 # def inner(): # print(x) # return inner # f=outter() # # def f1(): # x=1000000000 # f() # # f1() from urllib.request import urlopen
2、函数体内内部需要一个变量,有两种解决方案
#一种是:以参数的形式传入 def get(url): return urlopen(url).read() # get('http://www.baidu.com') # get('http://www.baidu.com') # get('http://www.baidu.com')
#另外一种:包起来 # def get(url): #url='http://www.baidu.com' # # url='http://www.baidu.com' # def inner(): # return urlopen(url).read() # return inner # # baidu=get('http://www.baidu.com') # print(baidu) # res=baidu() # baidu() # baidu() # baidu() # baidu()
另,
# def get(x,y): # def inner(): # print(x,y) # return inner # # baidu=get('a','b') # # print(baidu.__closure__[0].cell_contents) # print(baidu.__closure__[1].cell_contents) x,y=1,2 def get(): y=111111 def inner(): print(x,y) return inner baidu=get() print(baidu.__closure__)
3、简单装饰器
3.1、为什么要用装饰器:开放封闭原则,对扩展是开放的,对修改是封闭的
3.2、什么是装饰器
- 用来装饰它人,装饰器本身可以是任意可调用对象,被装饰器的对象也可以是任意可调用对象
- 遵循的原则:1、不修改被装饰对象的源代码 2、不修改被装饰对象的调用方式
- 目标是:在遵循原则1和2的前提,为被装饰器对象添加上新功能
import time def timmer(func): # func=index #最原始的index函数的内存地址 def inner(): start_time=time.time() func() stop_time=time.time() print('run time is :[%s]' %(stop_time-start_time)) return inner @timmer #index=timmer(index) def index(): time.sleep(3) print('welcome to index page') index()
4、装饰器修订
import time from functools import wraps def timmer(func): @wraps(func) def inner(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print('run time is :[%s]' %(stop_time-start_time)) return res return inner @timmer def index(): ''' index function :return: ''' time.sleep(3) print('welcome to index page') return 123 @timmer #home=timmer(home) #home=inner def home(name): time.sleep(2) print('welcome %s to home page' %name) return 456 # res=index() # res=inner() # print(res) # # res=home('egon') #inner('egon') # print(res) # print(index.__doc__) print(help(index))
5、有参装饰器
# import time # current_status={'user':None,'login_status':False} # # # def auth(func): # def inner(*args,**kwargs): # if current_status['user'] and current_status['login_status']: # res = func(*args, **kwargs) # return res # name=input('username>>:').strip() # pwd=input('password>>:').strip() # if name == 'egon' and pwd == '123': # print('login successfull') # current_status['user']=name # current_status['login_status']=True # res=func(*args,**kwargs) # return res # return inner # # @auth #index=auth(index) # def index(): # time.sleep(3) # print('welcome to index page') # return 123 # # @auth # def home(name): # time.sleep(2) # print('welcome %s to home page' %name) # return 456 # index() # home('egon')
另,
import time current_status={'user':None,'login_status':False} def auth(egine='file'): # egine='file' def wrapper(func): def inner(*args,**kwargs): if current_status['user'] and current_status['login_status']: res = func(*args, **kwargs) return res if egine == 'file': u='egon' p='123' elif egine == 'mysql': print('mysql auth') u = 'egon' p = '123' elif egine == 'ldap': print('ldap auth') else: pass name = input('username>>:').strip() pwd = input('password>>:').strip() if name == u and pwd == p: print('login successfull') current_status['user'] = name current_status['login_status'] = True res = func(*args, **kwargs) return res return inner return wrapper @auth(egine='ldap') #@wrapper #index=wrapper(index) #index=inner def index(): time.sleep(3) print('welcome to index page') return 123 index() #inner()
6、加多个有参装饰器
import time current_status={'user':None,'login_status':False} def timmer(func): def inner(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print('run time is :[%s]' %(stop_time-start_time)) return res return inner def auth(egine='file'): # egine='file' def wrapper(func): def inner(*args,**kwargs): if current_status['user'] and current_status['login_status']: res = func(*args, **kwargs) return res if egine == 'file': u='egon' p='123' elif egine == 'mysql': u = 'egon' p = '123' elif egine == 'ldap': u = 'egon' p = '123' else: pass name = input('username>>:').strip() pwd = input('password>>:').strip() if name == u and pwd == p: print('login successfull') current_status['user'] = name current_status['login_status'] = True res = func(*args, **kwargs) return res return inner return wrapper @timmer @auth(egine='ldap') #@wrapper #index=wrapper(timmer_inner) # @timmer #timmer_inner=timmer(index) def index(): time.sleep(3) print('welcome to index page') return 123 index() #inner()
test
import time from functools import wraps def timmer(func): #func=最原始的home函数的内存地址 @wraps(func) def inner(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print('run time is :[%s]' %(stop_time-start_time)) return res return inner @timmer #home=inner def home(name): ''' 这是home函数的注释信息 :param name: :return: ''' time.sleep(2) print('welcome %s to home page' %name) return 456 # home('egon') #inner('egon') # print(home.__doc__) print(help(home))
三、迭代器
1 什么叫迭代:迭代是一个重复过程,每次重复都是基于上一次的结果来的 2 为什么要用迭代器? l=['a','b','c'] n=0 while n < len(l): print(l[n]) n+=1 - 对于序列类型:字符串,列表,元组,可以使用基于索引的迭代取值方式,而对于没有索引的类型,如字典, 集合、文件,这种方式不再适用,于是我们必须找出一种能不依赖于索引的取值方式,这就是迭代器 3 可迭代的对象:只要对象内置有__iter__方法,obj.__iter__ 4 迭代器对象:对象既内置有__iter__方法,又内置有__next__,如文件对象 注意:可迭代对象不一定是迭代器对象,而迭代器对象一定是可迭代的对象
迭代器的优缺点: - 优点: 提供了一种统一的迭代取值方式,该方式不再依赖于索引 更节省内存 - 缺点: 无法统计长度 一次性的,只能往后走,不能往前退,无法获取指定位置的值
可迭代的对象
# 'hello'.__iter__ # [1,2].__iter__ # (1,2).__iter__ # {'a':1}.__iter__ # {1,2,3}.__iter__
既是可迭代对象,又是迭代器对象
# open('a.txt','w').__iter__ # open('a.txt','w').__next__
迭代器对象执行__iter__得到的仍然是它本身
# dic={'a':1,'b':2,'c':3} # iter_dic=dic.__iter__() # # print(iter_dic.__iter__() is iter_dic) # f=open('a.txt','w') # print(f is f.__iter__())
迭代器对象的用处
# dic={'a':1,'b':2,'c':3} # iter_dic=dic.__iter__() # print(iter_dic.__next__()) # print(next(iter_dic)) # print(next(iter_dic)) # print(next(iter_dic)) #StopIteration # with open('a.txt','r') as f: # print(next(f)) # print(next(f)) # print(next(f))
基于迭代器对象的迭代取值(不依赖索引)
# l=[1,2,3,4,5] # iter_l=l.__iter__() # print(iter_l) # print(next(iter_l)) # print(next(iter_l)) # print(next(iter_l)) #基于迭代器对象的迭代取值(不依赖索引) dic={'a':1,'b':2,'c':3} iter_dic=dic.__iter__() obj=range(10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) # list(obj) # while True: # try: # i=next(iter_dic) # print(i) # except StopIteration: # break # # for i in dic: #iter_dic=dic.__iter__() # print(i) 补充: from collections import Iterable,Iterator print(isinstance('hello',Iterable)) print(isinstance('hello',Iterator))
四、生成器
定义:只要函数内部出现yield关键字,那么再调用该函数,将不会立即执行函数体代码,会到到一个结果 该结果就是生成器对象
# def func(): # print('===>first') # yield 1 # print('===>second') # yield 2 # print('====>third') # yield 3 # # # g=func() # print(g) #生成器本质就是迭代器 # print(next(g)) # print(next(g)) # print(next(g)) # print(next(g)) # print(next(func())) # print(next(func())) # print(next(func())) # for i in g: # print(i) # # for i in g: # print(i) # # for i in g: # print(i)
yield的功能: - 为我们提供了一种自定义迭代器的方式 - 对比return,可以返回多次值,挂起函数的运行状态
#自定义功能,可以生成无穷多个值,因为同一时间在内存中只有一个值 # def my_range(start,stop,step=1): # while start < stop: # yield start # start+=step # g=my_range(1,5,2) #1 3 # print(next(g)) # print(next(g)) # print(next(g)) # print(next(g)) # print(next(g)) # # for i in my_range(1,1000000000000000000000000000000000000000000,step=2): # print(i)
例:
# tail -f access.log | grep '404' # import time # def tail(filepath): # with open(filepath,'rb') as f: # f.seek(0,2) # while True: # line=f.readline() # if line: # yield line # else: # time.sleep(0.2) # # def grep(pattern,lines): # for line in lines: # line=line.decode('utf-8') # if pattern in line: # yield line # # g=grep('404',tail('access.log')) # for line in g: # print(line)
yield的表达式形式的应用
# def eater(name): # food_list=[] # print('%s 开动啦' %name) # while True: # food=yield food_list #food=‘骨头’ # print('%s 开始吃 %s' %(name,food)) # food_list.append(food) # # g=eater('alex') # g.send(None) #next(g) # print(g.send('骨头')) # print(g.send('shi')) # def f1(): # while True: # x=yield # print(x) # # g=f1() # next(g) # g.send(1) # g.send(1) # g.close() # g.send(1) # g.send(1) # g.send(1)
五、面向过程编程
强调:面向过程编程绝对不是用函数编程那么简单 面向过程的编程思想:核心是过程二字,过程即解决问题的步骤,即先干什么再干什么 基于该思想去编写程序就好比在设计一条流水线,是一种机械式的编程思想 优点:复杂的问题流程化,进而简单化 缺点:可扩展性差
略难
# import os # g=os.walk(r'C:UsersAdministratorPycharmProjects19期day4a') # for dirname,_,files in g: # for file in files: # abs_file_path=r'%s\%s' %(dirname,file) # print(abs_file_path) #grep -rl 'root' /etc import os def init(func): def inner(*args,**kwargs): g=func(*args,**kwargs) next(g) return g return inner def search(filepath,target): #找到一个文件路径就往下个阶段传一次 g = os.walk(filepath) for dirname, _, files in g: for file in files: abs_file_path = r'%s\%s' % (dirname, file) target.send(abs_file_path) @init def opener(target): while True: abs_file_path=yield with open(abs_file_path,'rb') as f: target.send((f,abs_file_path)) @init def cat(target): while True: f,abs_file_path=yield for line in f: res=target.send((line,abs_file_path)) if res: break @init def grep(pattern,target): tag=False pattern = pattern.encode('utf-8') while True: line,abs_file_path=yield tag tag=False if pattern in line: target.send(abs_file_path) tag=True @init def printer(): while True: abs_file_path=yield print(abs_file_path) search(r'C:UsersAdministratorPycharmProjects19期day4a',opener(cat(grep('你好',printer()))))
六、三元表达式
# name=input('>>: ') # if name == 'alex': # print('SB') # else: # print('NB') # name = input('>>: ') # print('SB' if name == 'alex' else 'NB') def my_max(x,y): return x if x > y else y
十一、列表解析与生成器表达式
egg_list=[] for i in range(10): if i >= 3: res='egg%s' %i egg_list.append(res) # print(egg_list) # # # l=['egg%s' %i for i in range(10) if i >= 3] # print(l) # # g=('egg%s' %i for i in range(10) if i >= 3) # print(next(g)) # for i in ...: # if ...: # for i in ...: # if ...: # for ... names=['egon','alex_sb','wupeiqi','yuanhao'] names=[name.upper() for name in names if not name.endswith('sb')] print(names)
十二、序列化
# user={'name':'egon','pwd':'123'} # with open('db.txt','w',encoding='utf-8') as f: # f.write(str(user)) # with open('db.txt','r',encoding='utf-8') as f: # data=f.read() # print(data) import json # user={'name':'egon','pwd':'123','age':18} # with open('db.json','w',encoding='utf-8') as f: # f.write(json.dumps(user)) # with open('db.json','r',encoding='utf-8') as f: # data=f.read() # dic=json.loads(data) # print(dic['egon']) user={'name':'egon','pwd':'123','age':18} l=[1,2,3,'a'] json.dump(user,open('db1.json','w',encoding='utf-8')) # dic=json.load(open('db1.json','r',encoding='utf-8')) # print(dic,type(dic),dic['name'])
仍需总结!
函数递归