目录:python
1、装饰器算法
2、迭代器与生成器json
3、内置方法详解flask
4、Json与pickle数据序列化api
5、软件目录结构规范app
1、装饰器ssh
定义:装饰器自己是函数,(装饰其余函数),就是为其余函数添加附加功能。函数
原则:1.不能修改被装饰函数的源代码单元测试
2.不能修改被装饰函数的调用方式测试
装饰器应用详解
实现装饰器的知识储备:
1.函数即“变量”
2.高阶函数
3.嵌套函数
高阶函数+嵌套函数-->装饰器
__Author__ = 'Redleafage Zhang' import time def timmer(func): #装饰器 def warpper(*args,**kwargs): start_time = time.time() func() stop_time = time.time() print('the func run time is %s' %(stop_time-start_time)) return warpper @timmer def test1(): time.sleep(3) #运行逻辑所花费的时间 print('in the test1') test1()
打印结果:
1.装饰器之“函数即变量“
匿名函数:
calc = lambda x:x*3 #匿名函数,没有名字的函数 print(calc(3)) #返回9
变量名至关于门牌号,存放的内容至关于房间里的东西(占内存空间),函数名也至关于门牌号,函数体(函数的具体内容)在房间里面。以下图:
2.高阶函数:
a.把一个函数名看成实参传给另一个函数(在不修改被装饰函数源代码的状况下为其添加功能)
b.返回值中包含函数名(不修改函数的调用方式)
def bar(): print("in the bar!") def test1(func): print(func) func() 能够运行 test1(bar) #打印内存地址,bar只表明标示函数体的门牌号 func = bar func() #能够运行,传递地址,至关于x=1,y=x
打印结果:
def bar(): time.sleep(3) print('in the bar') def test2(func): print(func) return func #print(test2(bar)) #两次都打印地址 bar = test2(bar) #覆盖以前的bar函数,至关于test2加上了新功能,函数调用方式没有改变,python解释器有专门的符号可解释此过程,后面讲 bar() # run bar
打印结果:
import time def bar(): time.sleep(3) print('in the bar') def test1(func): start_time = time.time() func() #run bar stop_time = time.time() print('the func run time is %s' % (stop_time-start_time) ) test1(bar)
打印结果:
3.嵌套函数
def foo(): #函数的嵌套,嵌套指在函数内部以def形式定义新函数 print('in the foo') def bar(): #局部变量 print('in the bar') bar() foo()
def test1(): #这叫函数的调用,不是嵌套。 test2() test1()
局部做用域与全局做用域的访问顺序
x=0 def grandpa(): #x=1 def dad(): x=2 def son(): x=3 print(x) son() dad() grandpa() #结果返回3
实例:
__Author__ = 'Redleafage Zhang' import time def timer(func): def deco(*args,**kwargs): #是否传递参数都无所谓了 start_time = time.time() func(*args,**kwargs) #run test1 stop_time = time.time() print('the func run time is %s' %(stop_time-start_time)) return deco # def timer(): # def deco(): # pass @timer #至关于test1 = timer(test1) def test1(): time.sleep(3) print('in the test1') @timer #test2 = timer(test2)= deco test2() = deco() def test2(name,age): print('test2',name,age) #print(timer(test1)) #打印内存地址 #test1 = timer(test1) #test1() #-->deco test1() test2('linda',22)
打印结果:
终极实例:
__Author__ = 'Redleafage Zhang' import time user,passwd = 'alex','abc123' def auth(auth_type): print("auth func:",auth_type) def outer_wrapper(func): def wrapper(*args, **kwargs): print("wrapper func args:", func) if auth_type == 'local': username = input("Username:").strip() password = input("Password:").strip() if user == username and passwd == password: print("\033[32;1mUser has passed authentication\033[0m") res = func(*args, **kwargs) print("---after authentication") return res else: exit("\033[31;1mInvalid username or password\033[0m") elif auth_type == '1dap': print("搞毛线1dap,不会。。。") return wrapper return outer_wrapper def index(): print('welcome to index page') @auth(auth_type = 'local') def home(): print('welcome to home page') return 'from home' # 没执行结果,装饰器改变告终果 @auth(auth_type = '1dap') def bbs(): print('welcome to bbs page') index() print(home()) #wrapper() bbs()
打印结果:
2、迭代器与生成器
列表生成式:
[i*2 for i in range(10)] #生成[0,2,4,6,8,10,12,14,16,18]
生成器:
经过列表生成式,咱们能够直接建立一个列表。可是,收到内存限制,列表容量确定是有限的。并且,建立一个包含100万个元素的列表,不只占用很大的存储空间,若是咱们仅仅须要访问
前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
因此,若是列表元素能够按照某种算法推算出来,那咱们是否能够在循环的过程当中不断推算出后续的元素呢?这样就能够没必要建立完整的list,从而节省大量的空间,在python中,这种一边
循环一边计算的机制,称为生成器:generator。
要建立一个generator,有不少种方法。第一种方法很简单,只要把一个列表生成式的[]改为(),就建立了一个generator
1.生成器只有在调用时才会生成相应的数据
2.调用生成器下一个数据:__next__()
3.生成器只记录当前位置,只有一个next方法它不知道前面和后面,前面用完了就没了,不能往回调用。每次只保留一个值。
generator很是强大, 若是推算的算法比较复杂,用相似列表生成式的for循环没法实现的时候,还能够用函数来实现。
好比,著名的斐波那契数列(Fibonacci),除第一个和第二个数外,任意一个数均可以由前两个数相加获得:
1,1,2,3,5,8,13,21,34,……
斐波那契数列用列表生成式写不出来,可是,用函数把它打印出来却很容易:
def fib(max): n,a,b = 0,0,1 while n < max: print(b) a,b = b,a+b n = n+1 return 'done'
注意,赋值语句:
a,b = b,a+b
至关于
t = (b,a+b) #t是一个tuple a = t[0] b = t[1]
而不是至关于
a=b a=1 b=2 a=b a=2 b=a+b b=2+2 = 4
仔细观察,能够看出,fib函数其实是定义了斐波那契数列的推算规则,能够从第一个元素开始,推算出后续任意的元素,这种逻辑其实很是相似generator
也就是说,上面的函数和generator仅一步之遥。要把fib函数变成generator,只须要把print(b)改成yield b就能够了:
def fib(max): n,a,b = 0,0,1 while n < max: #print(b) yield b a,b = a,a+b n += 1 return 'done'
调用生成器:
print(fib(10)) #返回地址 f = fib(10) print(f.__next__()) print(f.__next__()) print(f.__next__())
打印结果:
实例:
__Author__ = 'Redleafage Zhang' import time def consumer(name): print("%s 准备吃包子啦!" %name) while True: baozi = yield #None,由于是生成器,返回值后再也不执行,再次输入__next__()才会继续执行 print("包子[%s]来了,被[%s]吃了!" %(baozi,name)) c = consumer("ChenRonghua") c.__next__() # b1= "韭菜馅" # c.send(b1) #把b1发送过去,被yield接收到 # c.__next__() def producer(name): c = consumer('A') #这一步只是把c变成生成器,不执行内容,next后才会开始执行 c2 = consumer('B') c.__next__() c2.__next__() print("老子开始准备作包子啦!") for i in range(10): time.sleep(1) print("作了1个包子,分两半!") c.send(i) c2.send(i) producer("alex")
打印结果:
迭代器
咱们已经知道,能够直接做用于for循环的数据类型有如下几种:
一类是集合数据类型,如list,tuple,dict,set,str等;
一类是generator,包括生成器和带yield的generator function.
这些能够直接做用于for循环的对象统称为可迭代对象:Iterable.
可使用isinstance()判断一个对象是不是Iterable对象:
能够被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator.
生成器确定是迭代器,迭代器不必定是生成器。
生成器都是Iterator对象,但list,dict,str虽然是Iterable,却不是Iterator
把list,dict,str等Iterable变成Iterator可使用iter()函数:
你可能会问,为何list,dict,str等数据类型不是Iterator?
这是由于Python的Iterator对象表示的是一个数据流,Iterator对象能够被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误,能够把这个数据流看做是
一个有序序列,但咱们却不能提早知道数列的长度,只能不断经过next()函数实现按需计算下一个数据,因此Iterator的计算是惰性的,只有在须要返回下一个数据时它才会计算。
Iterator甚至能够表示一个无限大的数据流,例如全体天然数。而使用 list 是永远不可能存储全体天然数的。(惰性计算:走到这一步再算,没走到就不算)
凡是可用于for循环的对象都是Iterable类型:
凡是可做用于 next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列:
集合数据类型如list,dict,str等是Iterable但不是Iterator,不过能够经过iter()函数得到一个Iterator对象。
3、内置方法详解
全部内置方法:
哈希:
若是直接搜索中文集,效率低,若是有500万个数据,则须要循环500万次,把无序的中文集经过映射转换为数字,并排序,查找的时候用折半查找的方式找对应的数字,提升效率。python
的字典是用哈希的方法实现的。MD5也属于哈希
内置函数详解:
__Author__ = 'Redleafage Zhang' print(all([0,-5,3])) #若是可迭代对象里全部的元素都为真(或者是空值),则返回真 print(any([0,-5.3]))#可迭代数据里任意的数据为真,则为真,若是是空的,则返回假 a=ascii([1,2,'开外挂了']) #把内容转换成字符串 print(type(a),[a]) print(bin(9)) #十进制转二进制 print(bool(1)) #判断真假 a=bytes("abcde",encoding="utf-8") b = bytearray("abcde",encoding="utf-8") print(b[0]) #打印ASCII码 b[1] = 100 #不能赋值字符串,只能赋ASCII码形式 # print(a) # print(a.capitalize(),a) 变大写,不改变原字符串 print(callable([])) #判断是否可调用,能加括号的可调用(好比函数),列表返回False print(chr(88)) #把数字对应ASCII码字符打印出来 print(ord('a')) #把字符转为ASCII码 code = "for i in range(10):print(i)" c = compile(code,'','exec')#exec表示能够把字符串之造成代码 exec(c) code = "1+3/2*6" #c = compile(code,'','eval') #eval计算数字 #eval(c) #CMD里可运行 eval(code) #CMD里可运行,把字符串变成字典 code = ''' def fib(max): n,a,b = 0,0,1 while n < max: #print(b) yield b a,b = b,a+b n = n+1 return 'done' #此时fib已是一个生成器,而不是一个函数,所以return是在异常测试时打印出来的东西,而不是函数的返回值 print(fib(10)) f = fib(10) print(f.__next__()) print(f.__next__()) print(f.__next__()) ''' py_obj = compile(code,"err.log",'exec') exec(py_obj) exec(code) #直接用exec也能够,compile没什么用 a = {} print(dir(a)) #查参数有什么方法能够用 print(divmod(5,2)) #相除并返回商和余数,归为元祖 def sayhi(n): #若是这个函数只使用一次,用def占用空间 print(n) for i in range(n): #此种lambda没法模拟 print(i) sayhi(3) #匿名函数,用完就释放,不占空间 print((lambda n:print(n))(5)) #(5)为传参 calc = lambda n:print(n) calc(5) #效果同上 calc = lambda n:3 if n<4 else n calc(5) res=filter(lambda n:n>5,range(10))#把大于5的过滤掉,返回迭代器 res = map(lambda n:n*2,range(10))#对传入的每一个值按逗号前的方法得出结果 [i*2 for i in range(10)] for i in res: print(i) res = [lambda i:i*2 for i in range(10)]#效果同上 import functools res = functools.reduce(lambda x,y:x+y,range(10)) #从1加到9,x+y的值返回x ,y为range(10)的下一个值 print(res) a = frozenset([1,4,333,212,33,33,12,4]) #不可变集合,不可增删 print(globals()) #返回当前整个程序全部变量的keyvalue的格式,变量名是key,变量名对应的值是value print(hash('alex')) #把字符变成映射的数字 print(hex(122)) #把数字转成16进制 def test(): local_var = 333 print(locals()) #打印当前函数全部的局部变量,以字典的形式 print(globals()) #打印结果无局部变量 test() print(globals().get('local_var')) #没法取到函数里的值,global只打印全局变量,不打印局部变量 print(oct(10)) #转八进制 print(pow(3,5)) #3的5次方 round(1.3342,2) #保留两位小数 slice(2,5,None) d = range(10) d[slice(2,5)] #至关于d[2:5],没什么用 a = {6:2,8:0,1:4,-5:6,99:11,4:22} print(sorted(a.items())) #把无序的字典按key排序 print(sorted(a.items(),key = lambda x:x[1])) #把无序的字典按value排序 print(a) #无序 a = [1,2,3,4] b = ['a','b','c','d'] for i in zip(a,b): #拼两个列表,返回元组 print(i) __import__('decorator') #之后会用到
打印结果:
/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6 /Users/zhangshu/PycharmProjects/s14/day4/内置方法.py False True <class 'str'> ["[1, 2, '\\u5f00\\u5916\\u6302\\u4e86']"] 0b1001 True 97 False X 97 0 1 2 3 4 5 6 7 8 9 <generator object fib at 0x10410d200> 1 1 2 <generator object fib at 0x10410d2b0> 1 1 2 ['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values'] (2, 1) 3 0 1 2 5 None 5 0 2 4 6 8 10 12 14 16 18 45 {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x101eb85c0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/zhangshu/PycharmProjects/s14/day4/内置方法.py', '__cached__': None, '__Author__': 'Redleafage Zhang', 'a': frozenset({1, 33, 4, 12, 333, 212}), 'b': bytearray(b'adcde'), 'code': "\ndef fib(max):\n n,a,b = 0,0,1\n while n < max:\n #print(b)\n yield b\n a,b = b,a+b\n n = n+1\n return 'done' #此时fib已是一个生成器,而不是一个函数,所以return是在异常测试时打印出来的东西,而不是函数的返回值\n\nprint(fib(10))\nf = fib(10)\nprint(f.__next__())\nprint(f.__next__())\nprint(f.__next__())\n", 'c': <code object <module> at 0x1040f5a50, file "", line 1>, 'i': 18, 'py_obj': <code object <module> at 0x1040f5b70, file "err.log", line 2>, 'fib': <function fib at 0x104108598>, 'f': <generator object fib at 0x10410d2b0>, 'sayhi': <function sayhi at 0x101e62ea0>, 'calc': <function <lambda> at 0x104108ae8>, 'res': 45, 'functools': <module 'functools' from '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/functools.py'>} -652459854530933945 0x7a {'local_var': 333} {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x101eb85c0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/zhangshu/PycharmProjects/s14/day4/内置方法.py', '__cached__': None, '__Author__': 'Redleafage Zhang', 'a': frozenset({1, 33, 4, 12, 333, 212}), 'b': bytearray(b'adcde'), 'code': "\ndef fib(max):\n n,a,b = 0,0,1\n while n < max:\n #print(b)\n yield b\n a,b = b,a+b\n n = n+1\n return 'done' #此时fib已是一个生成器,而不是一个函数,所以return是在异常测试时打印出来的东西,而不是函数的返回值\n\nprint(fib(10))\nf = fib(10)\nprint(f.__next__())\nprint(f.__next__())\nprint(f.__next__())\n", 'c': <code object <module> at 0x1040f5a50, file "", line 1>, 'i': 18, 'py_obj': <code object <module> at 0x1040f5b70, file "err.log", line 2>, 'fib': <function fib at 0x104108598>, 'f': <generator object fib at 0x10410d2b0>, 'sayhi': <function sayhi at 0x101e62ea0>, 'calc': <function <lambda> at 0x104108ae8>, 'res': 45, 'functools': <module 'functools' from '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/functools.py'>, 'test': <function test at 0x104108bf8>} None 0o12 243 [(-5, 6), (1, 4), (4, 22), (6, 2), (8, 0), (99, 11)] [(8, 0), (6, 2), (1, 4), (-5, 6), (99, 11), (4, 22)] {6: 2, 8: 0, 1: 4, -5: 6, 99: 11, 4: 22} (1, 'a') (2, 'b') (3, 'c') (4, 'd') in the test1 the func run time is 3.002807140350342 Process finished with exit code 0
4、Jason与pickle数据序列化
Json:多语言可用,只能存放简单数据
Pickle:只有python能用,能存放复杂数据(如函数)
import json info = { 'name':'alex', 'age':22 } f = open('test.text','w') print(json.dumps(info)) f.write(json.dumps(info)) #直接以字典格式存入文件 f = open('test.text','r') data = json.loads(f.read()) #恢复数据 print(data['age'])
打印结果:
pickle:
import pickle def sayhi(name): print("hello",name) info = { 'name':'alex', 'age':22, 'func':sayhi #pickel能够存储函数,而json不行 } f = open("test.text",''wb") print(pickle.dumps(info)) f.write(pickle.dumps(info)) #直接以字典格式存入文件 f = open("test.text","rb") data = pickle.loads(f.read()) #恢复数据 print(data)
打印结果:
注:pickle.dump(info,f) 等同于f.write(pickle,dumps(info))
data = pickle.load(f) 等同于pickle.loads(f.read())
写程序时每dump一次,就要loadi 次,不要一次dump不少行,宁肯dump成好几个文件。
5、软件目录结构规范
1.bin/: 存放项目的一些可执行文件,固然你能够起名script/之类的也行。
2.foo/:存放项目的全部源代码。(1)源代码中的全部模块、包都应该放在此目录。不要只置于顶层目录。(2)其子目录test/存放单元测试代码;(2)程序的入口最好命名为main.py
3.docs/:存放一些文档
4.setup.py:安装、部署、打包的脚本
5.requirements.txt:存放软件依赖的外部Python包列表
6.README:项目说明文件
除此以外,有一些方案给出了更多的内容。好比ICENSE.txt,ChangeLog.txt文件等,通常开源的时候会用到。
关于README的内容:
这个是每一个项目都应该有的一个文件,目的是要能简要描述该项目的信息,让读者快速了解这个项目。
它须要说明如下几个事项:
1.软件定位,软件的基本功能。
2.运行代码的方法:安装环境、启动命令等。
3.简要的使用说明。
4.代码目录结构说明,更详细点能够说明软件的基本原理。
5.常见问题说明。
requirements.txt:
这个文件存在的目的是:
1.方便开发者维护软件的包依赖。将开发过程当中新增的包添加进这个列表中,避免在setup.py安装依赖时漏掉软件包。
2.方便读者明确项目使用了哪些Python包。
这个文件的格式是每一行包含一个包依赖的说明。一般是flask >= 0.10这种格式,要求是这个格式能被pip识别,这样就能够简单的经过pip install -r requirements.txt来把全部的python包依赖
都安装好了。
注意:从foo调main须要跨目录
经过os方法找到主目录,添加给环境变量,再导入其它模块便可。