python_day3(文件操作、函数基础、装饰器)
一、文件操作
r 模式是读文件 f=open(r"C:\test.py","r",encoding="utf-8") #第一个参数的r是源字符不转义 第二个参数的"r" 默认是"rt" 已文本的格式打开,第三个参数是打开文件的字符编码,(默认是操作系统的编码) f.close() #通知操作系统关闭文件 f=open("a.txt","r",encoding="utf-8") data = f.read() #一次性读文件所有内容存储成一个字符串,光标移动到文件末尾 print(data,end="") #print的end="" 的参数为取掉print末尾自带的换行符 data = f.readlines() # 一次性把文件读到一个列表中,一行一个元素,光标移动到文件末尾 print(data,end="") data = f.readline() # 一次读取一行,光标移动到下一行 print(data,end="") #False f.close() #w 模式是写文件如文件不存在创建文件,如文件存在覆盖文件内容,光标会移动到文件头 f=open("a.txt","r",encoding="utf-8") print(f.writable()) #文件是否可写 #False f.close() f=open("a.txt","w",encoding="utf-8") print(f.writable()) #True f.write("1111111\n") f.write("2222222\n") f.writelines(["333\n","4444\n"]) f.close() #a 模式为追加写文件不存在创建文件,如文件存在追加写,光标会移动到文件末尾 f=open("a.txt","a",encoding="utf-8") print(f.writable()) #文件是否可写 #True f.close() f=open("a.txt","a",encoding="utf-8") f.write("333\n") f.write("4444\n") f.writelines(["5555\n","6666\n"]) f.close() with open("a.txt","r",encoding="utf-8") as f: while True: #line = f.readline() if len(f.readline()) == 0: break print(f.readline(),end="") # 2222222 # 4444 # 4444 # 6666 #为啥会出现少文件,是因使用一次f.readline 后光标会移动到下一行所以在判断完以后光标就移动到了下一行所以在此print f.readline 的时候是在下一行,所以应该把f.readline 赋值如下 with open("a.txt","r",encoding="utf-8") as f: while True: line = f.readline() if len(line) == 0: break print(line,end="") # 1111111 # 2222222 # 333 # 4444 # 333 # 4444 # 5555 # 6666 #通过for循环文件来打印 with open("a.txt","r",encoding="utf-8") as f: for line in f: print(line,end="") # 1111111 # 2222222 # 333 # 4444 # 333 # 4444 # 5555 # 6666 在打开非文件格式的时候用"b"模式读和写没有字符编码的概念了 "b"模式可以理解为二进制读,所以可以读任何格式的文件。但是文本格式b模式下是可以进行编码的 with open("a.txt","rb") as f: line = f.read() print(line) #b'\xe5\x90\x95\xe5\x85\xb4\xe5\x9b\xbd' # 此处的b模式就是 python2 的str模式就是定义变量的模式,所以在python2中若要跨平台打印应该先把python2的str的字符串用decode方法转换成 unicode格式 line = line.decode("utf-8") print(line) # 吕兴国 with open("a.txt","wb") as f: #f.write("holle word") #TypeError: a bytes-like object is required, not 'str' f.write("吕兴国 哈哈".encode("utf-8")) #以utf-8 的格式转换成bytes存。 print("吕兴国 哈哈".encode("utf-8")) #b'\xe5\x90\x95\xe5\x85\xb4\xe5\x9b\xbd \xe5\x93\x88\xe5\x93\x88' print(type("吕兴国 哈哈".encode("utf-8"))) #<class 'bytes'> cp with 可以同时打开多个文件用逗号隔开如: with open("a.txt","rb") as read_file , open("b.txt","wb") as write_file: for line in read_file: read_file.write(line) read_file.flush() #把写的内容从内存刷到磁盘 ###小知识点######## python传参导入模块 sys import sys #print(sys.argv) #sys.argv 为一个列表,列表的第一个元素为文件的路径,此后的元素为所传的参数 _,src_file,dst_file = sys.argv with open(src_file,"rb") as read_file , open(dst_file,"wb") as write_file: for line in read_file: read_file.write(line) 文件的修改 python 导入模块 os import os with open("info.txt" ,"r",encoding="utf-8") as f, open(".info.txt.swap","w",encoding="utf-8") as f_tmp: data = f.read() #print(data) f_tmp.write(data.replace("alex","lxg")) os.remove("info.txt") os.rename(".info.txt.swap","info.txt") #更佳 with open("info.txt" ,"r",encoding="utf-8") as f, open(".info.txt.swap","w",encoding="utf-8") as f_tmp: for line in f: if "alex" in line: line = line.replace("alex","lxg") f_tmp.write(line) os.remove("info.txt") os.rename(".info.txt.swap","info.txt") ####小结######## 3. 了解部分 "+" 表示可以同时读写某个文件 r+, 读写【可读,可写】 w+,写读【可读,可写】 a+, 写读【可读,可写】 x, 只写模式【不可读;不存在则创建,存在则报错】 x+ ,写读【可读,可写】 xb 掌握 f.read() #读取所有内容,光标移动到文件末尾 f.readline() #读取一行内容,光标移动到第二行首部 f.readlines() #读取每一行内容,存放于列表中 f.write('1111\n222\n') #针对文本模式的写,需要自己写换行符 f.write('1111\n222\n'.encode('utf-8')) #针对b模式的写,需要自己写换行符 f.writelines(['333\n','444\n']) #文件模式 f.writelines([bytes('333\n',encoding='utf-8'),'444\n'.encode('utf-8')]) #b模式 #了解 f.readable() #文件是否可读 f.writable() #文件是否可读 f.closed #文件是否关闭 f.encoding #如果文件打开模式为b,则没有该属性 f.flush() #立刻将文件内容从内存刷到硬盘 f.name 文件光标移动 f.tell() 当前光标的位置 为字节的位置 只有一种情况下光标的位置为字符为在 文件已"rt"模式打开时 f.read(3) 中的3为字符 f.seek() 光标的移动f.seek(0,0) 第一个参数移动的字节,第二个参数为参照物 0,为文件开头(默认,可在"b" 和 "t"模式下使用),2为文件末尾(在"b"的模式下用) 1为当前模式(在"b"的模式下用) 模仿 tail -f 导入模块 time import time with open("access.log","rb") as f: f.seek(0,2) while True: line = f.readline() #print(line) if line: print(line.decode("utf-8"),end="") else: time.sleep(0.05) 截断文件 with open("access.log","a",encoding="utf-8") as f: f.truncate(3) #已文件开头为参照物,保留3个字节
二、函数基础
1 为什么要有函数?没有函数带来的困扰?
组织结构不清晰,可读性差
代码冗余
可扩展性差
2 什么是函数
具备某一个功能的工具---》函数
事先准备工具-》函数的定义
拿来就用、重复使用-》函数的调用
ps:先定义后调用
3 函数的分类:
内置函数:len,max(10,11),help(函数名)查看函数的帮助信息
自定义函数:def
语法:
def 函数名(参数1,参数2,...):
"""注释"""
函数体
return 返回值
1、'函数即是变量' def print_tag(): print('*'*20) def print_msg(): #print_msg=<function print_msg at 0x00000000027EA8C8> print('hello world') # print(print_msg) # print(print_tag) print_tag() print_msg() print_tag() 2、定义函数阶段都发生了什么事:只检测语法,不执行代码 定义阶段 sex='male' def auth(): sex abc #只要在调用截断存在就行 name=input('name>>: ').strip() password=input('password>>: ').strip() if name =='egon' and password == '123': print('login successfull') else: print('user or password err') #调用阶段 auth() 3、函数的使用:先定义后调用 def bar(): print('from bar') def foo(): print('from foo') bar() foo() #定义阶段 def foo(): print('from foo') bar() #foo() #报错定位bar没有定义 def bar(): print('from bar') #调用 foo() #在调用是bar存在即可不会报错 4 定义函数的三种形式 第一种:无参函数 第二种:有参函数 第三种:空函数 def auth(): name=input('name>>: ').strip() password=input('password>>: ').strip() if name =='egon' and password == '123': print('login successfull') else: print('user or password err') def my_max(x,y): if x >= y: print(x) else: print(y) my_max(1,2) def auth(name,password): if name =='egon' and password == '123': print('login successfull') else: print('user or password err') def interactive(): name=input('name>>: ').strip() password=input('password>>: ').strip() auth(name,password) interactive() 5、空函数 def auth(): pass
函数的返回值
#return的特点: #1、 函数内可以有多个return,但是只能执行一次return #2、 执行return函数就立刻结束,并且return的后值当做本次调用的结果返回 def foo(x,y): return x+y res=foo(1,2) print(res) #3 def my_max(x,y): if x >= y: return x else: return y res=my_max(1,2) print(res) #2 def foo(): print('first') return 1 #返回 1 然后退出函数 print('second') return 2 #不会执行 print('third') return 3 #不会执行 res=foo() print(res) #1 #1、返回的值没有类型限制 def bar(): print('from bar') def foo(): return bar print(foo() is bar) #True #2:return返回值的个数 #2.1: 没有return:默认返回None #2.2:return 值:值本身 #3.3: return 多个值:返回一个元组 def foo(): pass return 1,'a',[1,2] print(foo()) #(1, 'a', [1, 2]) #函数调用的三种形式 def my_max(x,y): if x >= y: return x else: return y res1=my_max(1,2) print(res1) #2 res2=my_max(1,2)*10 #返回值计算 print(res2) #20 res3=my_max(my_max(1,2),3) print(res3) #3
函数参数
#函数的参数分类两种: #形参:在定义阶段括号内指定的参数,相当于变量名 形参的类型有 位置形参,默认形参,可变长形参,命名关键字形参(必须以key——value的格式传参) #实参:在调用阶段括号内传入的值称之为实参,相当于值 实参的类型有:位置实参,关键字实参,可变长的位置实参,可变长的关键字实参 #在调用阶段,实参的值会绑定给形参,在调用结束后解除绑定 def foo(x,y): #x和y就是形参 print(x,y) foo(1,2) #1,2就是实参 #1 2 #在python中参数的分类: #1、位置参数:按照从左到右的顺序依次定义的参数 #位置形参:必须被传值,多一个少一个都不行 并不是按照位置传值 #位置实参:与形参一一对应传值 # def foo(x,y): # print(x,y) # # foo(2,1) #x---->2 1------>y #2、关键字参数(实参):在函数调用时,按照key=value的形式定义的实参 可以定义任何参数且没有位置的限制 #特点:指名道姓地给形参传值,不再依赖与位置 def foo(name,age,sex): print(name,age,sex) foo('egon',18,'male') #egon 18 male foo(sex='male',age=18,name='egon',) #egon 18 male #注意: #1、 关键字实参必须在位置实参的后面 #2、 不能为同一个参数赋值多次 foo('egon',sex='male',age=18,name='egon') #TypeError: foo() got multiple values for argument 'name' #3、默认参数:在函数定义阶段,就已经为形参赋值了 #特点:定义阶段已经有值意味着调用阶段可以不用传值 #位置参数通常用于经常变化的参数,而默认参数指的是大多数情况下都一样的 def foo(x,y=1): print(x,y) foo(1,2) #1 2 foo(y=3,x=1) #1 3 foo(111) #111 1 foo(x=1111) #1111 1 def register(name,age,sex='male'): print(name,age,sex) register('egon1',18) #egon1 18 male register('egon2',18) #egon2 18 male register('egon3',18) #egon3 18 male register('alex',38,'female') #alex 38 female #注意: #1、默认参数必须放到位置形参的后面 def register(name,sex='male',age,): print(name,age,sex) #SyntaxError: non-default argument follows default argument #2、默认参数的值只在定义时被赋值一次 #3、默认的参数的值通常应该是不可变类型 res=1 def foo(x,y=res): print(x,y) res=10 foo('aaaaaaaa') #aaaaaaaa 1 #4 可变长参数:在调用函数时,实参值的个数不固定 #实参的形式有:位置实参和关键字实参,位置参数是 *list 关键字参数是**dict #形参的解决方案:*,** #*args的用法 def foo(x,y,*args): #z=(3,4,5,6) print(x,y) print(args) # foo(1,2,3,4,5,6) foo(1,2,*[3,4,5,6]) #foo(1,2,3,4,5,6) # 1 2 # (3, 4, 5, 6) foo(*[1,2,3,4,5,6]) #foo(1,2,3,4,5,6) # 1 2 # (3, 4, 5, 6) def foo(x,y): print(x,y) foo(*(1,2)) #foo(1,2) #1 2 #**kwargs def foo(x,y,**kwargs): #kwargs={'c':5,'a':3,'b':4} print(x,y) print(kwargs) # foo(y=2,x=1,a=3,b=4,c=5) foo(y=2,**{'c':5,'x':1,'b':4,'a':3}) #foo(y=2,a=3,c=5,b=4) #1 2 #{'c': 5, 'b': 4, 'a': 3} def foo(name,age): print(name,age) foo(**{'name':'egon','age':18}) #egon 18 #foo({'name':'egon','age':18}) #TypeError: foo() missing 1 required positional argument: 'age' def bar(x,y,z): print(x,y,z) def wrapper(*args,**kwargs): #args=(1,),kwargs={'z':2,'y':3} # print(args,kwargs) bar(*args,**kwargs) #bar(*(1,),**{'z':2,'y':3}) #bar(1,z=2,y=3,) wrapper(1,z=2,y=3) #1 3 2 #命名关键字参数:指的是定义在*后的参数,该参数必须被传值(除非有它有默认值),而且必须按照key=value的形式传值 def foo(x,y,*args,m=100000,n): print(x,y) print(args) print(m,n) foo(1,2,3,n=4,) #1 2 #(3,) #100000 4
函数对象
#函数是第一类对象:指的是函数可以当做数据传递 #1、可以被引用 x=1,y=x def func(x,y): print(x,y) f=func f(1,2) #1 2 #2、可当做函数的参数传入 def foo(): print('from foo') def bar(func): # print(func) func() bar(foo) #from foo #3、可以当做函数的返回值 def foo(): print('from foo') def bar(): return foo f=bar() f() #from foo #4、可以当做容器类型的元素 def foo(): print('from foo') def bar(): return foo l=[foo,bar] print(l) #[<function foo at 0x102246620>, <function bar at 0x102246730>] l[0]() #from foo # def get(): # print('get') # # def put(): # print('put') # # def ls(): # print('ls') # # cmd=input('>>: ').strip() # if cmd == 'get': # get() # elif cmd == 'put': # put() # elif cmd == 'ls': # ls() def get(): print('get') def put(): print('put') def ls(): print('ls') def auth(): print('auth') func_dic={ 'get':get, 'put':put, 'ls':ls, 'auth':auth } # func_dic['put']() cmd = input('>>: ').strip() if cmd in func_dic: func_dic[cmd]()
函数嵌套
#1、函数的嵌套调用 def my_max(x,y): if x >= y: return x else: return y def my_max4(a,b,c,d): res1=my_max(a,b) res2=my_max(res1,c) res3=my_max(res2,d) return res3 #2、函数的嵌套定义 def f1(): def f2(): print('from f2') def f3(): print('from f3') f3() # print(f2) f2() f1() # from f2 # from f3
名称空间和作用域
#名称空间指的是:存放名字与值绑定关系的地方, #内置名称空间(python解释器启动就有):python解释器内置的名字,max,len,print #全局名称空间(执行python文件时生效):文件级别定义的名字 # x=1 # def func():pass # import time # if x == 1: # y=2 #以上全都在全局名称空间 #局部名称空间(函数调用时生效,调用结束失效):函数内部定义的名字, # func() #加载顺序:内置---》全局----》局部名称空间 #访问名字的顺序:局部名称空间===》全局----》内置 x=1 print(x) #1 print(max) #<built-in function max> max=2 def func(): # max=1 print(max) func() #2 x='gobal' def f1(): # x=1 def f2(): # x=2 def f3(): # x=3 print(x) f3() f2() f1() #gobal #全局作用域(全局范围):内置名称空间与全局名称空间的名字,全局存活,全局有效,globals() #局部作用域(局部范围):局部名称空间的名字,临时存活,局部有效,locals() xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=111111111111111111111 print(globals()) #{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x1007d8518>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/lvxingguo/PycharmProjects/oldboy/day3/2 装饰器系列/3 名称空间.py', '__cached__': None, 'x': 'gobal', 'max': 2, 'func': <function func at 0x101a46510>, 'f1': <function f1 at 0x101a46620>, 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx': 111111111111111111111} print(dir(globals()['__builtins__'])) #内置的名称空间 #['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip'] print(locals() is globals()) #True def func(): yyyyyyyyyyyyyyyyyyyyyyyy=22222222 print(globals()) print(locals()) func() #{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x1006d8518>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/lvxingguo/PycharmProjects/oldboy/day3/2 装饰器系列/3 名称空间.py', '__cached__': None, 'x': 'gobal', 'max': 2, 'func': <function func at 0x102a46620>, 'f1': <function f1 at 0x102a46510>, 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx': 111111111111111111111} #{'yyyyyyyyyyyyyyyyyyyyyyyy': 22222222} x=100 def func(): global x #声明x是全局变量 x=1 func() print(x) #1 x='global' def f1(): #nonlocal x x=1 def f2(): nonlocal x #声明x为上一层(直到找到为止,但只限于函数内部)名称空间的值 如果上一层没有x报错 #SyntaxError: no binding for nonlocal 'x' found #global x x=0 f2() print('===f1 innter--->',x) f1() print(x) #===f1 innter---> 0 #global #强调两点: #1、打破函数层级限制来调用函数 def outter(): def inner(): print('inner') return inner f=outter() # print(f) f() #inner def bar(): f() bar() #inner #2、函数的作用域关系是在函数定义阶段就已经固定了,与调用位置无关 x=1 def outter(): # x=2 def inner(): print('inner',x) return inner f=outter() # print(f) # x=11111111111111111 def bar(): x=3 f() # x=1111111111111111 bar() #inner 1 x=111111111111111111
闭包函数
#闭包函数: #1 定义在函数内部的函数 #2 该函数的函数体代码包含对外部作用域(而不是全局作用域)名字的引用 #3 通常将闭包函数用return返回,然后可以在任意位置使用 z=1 def outer(): x=1 y=2 def inner(): print(x,y) # print(z) return inner f=outer() print(f.__closure__[0].cell_contents) #查看闭包函数对外部作用域引用的值 其中f.__closure__[0] 是指的内存空间值 #1 print(f.__closure__[1].cell_contents) #2 print(f.__closure__) #(<cell at 0x10065f288: int object at 0x10028bc20>, <cell at 0x102932618: int object at 0x10028bc40>) def bar(): x=111121 y=2222 f() bar() #1 2 # def foo(x,y): # print(x+y) # # foo(1,2) # def outter(): # x=1 # y=2 # def foo(): # print(x+y) # return foo # # # f=outter() # # f() #爬页面:闭包函数为我们提供了一种新的为函数传参的方式 import requests #pip3 install requests # def get(url): # response=requests.get(url) # if response.status_code == 200: # print(len(response.text)) # # get('https://www.baidu.com') # get('https://www.baidu.com') # get('https://www.baidu.com') def outter(url): # url = 'https://www.baidu.com' def get(): response=requests.get(url) if response.status_code == 200: print(len(response.text)) return get baidu=outter('https://www.baidu.com') python=outter('https://www.python.org') # baidu() # baidu() # baidu() #此法更方便
装饰器
#1、开放封闭原则:对扩展开放,对修改是封闭 #2、装饰器:装饰它人的,器指的是任意可调用对象,现在的场景装饰器-》函数,被装饰的对象也是-》函数 #原则:1、不修改被装饰对象的源代码 2、不修改被装饰对象的调用方式 #装饰器的目的:在遵循1,2的前提下为被装饰对象添加上新功能 #错误的示范 # import time # # def index(): # time.sleep(3) # print('welecome to index') # # def timmer(func): # start=time.time() # func() # stop=time.time() # print('run time is %s' %(stop-start)) # # timmer(index) import time def index(): time.sleep(3) print('welecome to index') def timmer(func): # func=index #最原始的index def inner(): start=time.time() func() #最原始的index stop=time.time() print('run time is %s' %(stop-start)) return inner index=timmer(index) #index=inner print(index) #<function timmer.<locals>.inner at 0x102a46620> index() #inner() #welecome to index #run time is 3.0044898986816406 #装饰器语法:在被装饰对象正上方单独一行写上,@装饰器名 #改进一: import time def timmer(func): def inner(): start=time.time() res=func() stop=time.time() print('run time is %s' %(stop-start)) return res return inner @timmer #index=timmer(index) def index(): time.sleep(1) print('welecome to index') return 1111 res=index() #res=inner() print(res) #改进二: import time def timmer(func): def inner(*args,**kwargs): start=time.time() res=func(*args,**kwargs) stop=time.time() print('run time is %s' %(stop-start)) return res return inner # @timmer #index=timmer(index) # def index(name): # time.sleep(1) # print('welecome %s to index' %name) # return 1111 # res=index('egon') #res=inner('egon') # print(res) @timmer #home=timmer(home) def home(name): print('welcome %s to home page' %name) home('egon') #inner('egon') #有参装饰器 import time def auth2(engine='file'): def auth(func): # func=index def inner(*args,**kwargs): if engine == 'file': name=input('name>>: ').strip() password=input('password>>: ').strip() if name == 'egon' and password == '123': print('login successful') return func(*args,**kwargs) else: print('login err') elif engine == 'mysql': print('mysql auth') elif engine == 'ldap': print('ldap auth') else: print('engin not exists') return inner return auth @auth2(engine='mysql') #@auth #index=auth(index) #index=inner def index(name): time.sleep(1) print('welecome %s to index' %name) return 1111 res=index('egon') #res=inner('egon') print(res) #并列多个装饰器 import time def timmer(func): def inner(*args,**kwargs): start=time.time() res=func(*args,**kwargs) stop=time.time() print('run time is %s' %(stop-start)) return res return inner def auth2(engine='file'): def auth(func): # func=index def inner(*args,**kwargs): if engine == 'file': name=input('name>>: ').strip() password=input('password>>: ').strip() if name == 'egon' and password == '123': print('login successful') return func(*args,**kwargs) else: print('login err') elif engine == 'mysql': print('mysql auth') elif engine == 'ldap': print('ldap auth') else: print('engin not exists') return inner return auth @auth2(engine='file') @timmer def index(name): time.sleep(1) print('welecome %s to index' %name) return 1111 res=index('egon') print(res) #wraps 把原函数的信息替换到装饰器的函数中 from functools import wraps import time def timmer(func): @wraps(func) def inner(*args,**kwargs): start=time.time() res=func(*args,**kwargs) stop=time.time() print('run time is %s' %(stop-start)) return res # inner.__doc__=func.__doc__ # inner.__name__=func.__name__ return inner @timmer def index(name): #index=inner '''index 函数。。。。。''' time.sleep(1) print('welecome %s to index' %name) return 1111 # res=index('egon') # print(res) print(help(index))