三、列表生成式 list_new = [ x*2 for x in range(10) ] #生成[0,2,4,6,8,10,12,14,16,18] print(list_new) def func(x): return x**2 list_new = [ func(x) for x in range(10) ] #range(10)的每一个元素都传递给func() print(list_new)
四、生成器 与列表生成式不同,列表生成式会在执行时直接生成一个全量的列表,比如rang(10000000),则会生成一个1千万元素的列表,非常占用内存空间。 生成器:( x*2 for x in range(10000000) )执行后产生一个generator object。这个对象就叫做生成器。使用生成器来循环列表,只会根据当前循环的次数实时产生列表元素,大量节省内存空间。 性能比较如下代码:利用前面所学的装饰器给两个循环函数加上运行时间。得出结果,生成式耗时2s,而生成器耗时几乎为0。 import time def timer(func): def wrapper(*args,**kwargs): start_time = time.time() func(*args,**kwargs) end_time = time.time() print("Time : %s" % (end_time-start_time)) return wrapper def func(x): return x*2 @timer def list_new_loop(): list_new = [ func(x) for x in range(10000000) ] print(type(list_new)) for i in list_new: if i ==100: break print(i) @timer def list_new2_loop(): list_new2 = ( func(x) for x in range(10000000)) print(type(list_new2)) for i in list_new2: if i ==100: break print(i) list_new_loop() list_new2_loop()
生成式和生成器的区别: 除了在循环中存在内存空间占用的区别。 另外还有一个很重要的区别: 生成器不能直接用下标取值,因为他并未在内存中存放实际列表的元素。必须循环到某个下标才能实时生成元素并取值。 可以使用__next__()实时生成下一个元素并取值。 l = ( x*2 for x in range(100)) print(l.__next__()) #同next(l) 但是没有方法可以取到前面的值。因为生成器为了节省内存,只记住当前位置的元素,前面使用过的就扔掉了。 另一种生成器产生方法:(前一种方法的底层实现是这种函数方法) 下面函数打印一个斐波那契数列: #斐波那契 def feibonaq(max_num): n ,a ,b = 0 ,0 ,1 while n < max_num: print(b) a , b = b , a+b n += 1 feibonaq(20) 将其中的print(b)替换为yield b。则feibonaq()返回一个生成器。 #斐波那契 def feibonaq(max_num): n ,a ,b = 0 ,0 ,1 while n < max_num: yield b #使用yield b a , b = b , a+b n += 1 f = feibonaq(20) #返回一个<generator object feibonaq at 0x02B47360> print(f.__next__()) #获取一个b的值,也可以用next(f) print(f.__next__()) #获取下一个b的值 print(f.__next__()) print("Do other things") #可以做其他事情 print(f.__next__()) #再取下一个b的值 yield返回当前状态的值,该函数并停在这里,等执行完其他操作后,再次执行next时,再回来继续执行。 给yield传值: def consumer(name): print("%s 准备吃包子啦!" % name) while True: baozi = yield #使consumer返回一个生成器generator,接受参数并赋值给baozi print("包子 [%s] 来了,被 [%s] 吃了!" % (baozi,name)) c = consumer("Leo") #返回一个生成器给c c.__next__() #开始触发生成器(必须) bz = "韭菜馅包子" c.send(bz) #传递参数给yield(重要) 单线程下实现并行效果:(nginx就是这种原理,单线程下并发效率比多线程还高)异步IO的雏形。 import time def consumer(name): print("%s 准备吃包子啦!" % name) while True: baozi = yield print("[%s] 被 [%s] 吃了!" % (baozi,name)) def productor(name): c = consumer("Leo") c1 = consumer("Kale") c.__next__() c1.__next__() print("[%s] 开始做包子了!" % name) for i in range(10): time.sleep(0.5) baozi_half = "包子的一半" baozi_other_half = "包子的另一半" print("老子做了一个包子,分成两半!") c.send(baozi_half) c1.send(baozi_other_half) productor("cooker") 程序解释: 为什么在c = consumer()后必须执行一次c.__next__()。以为c = consumer()只是将consumer函数变成一个生成器。第一次调用__next__(),是为了将程序走到baozi = yield这一步,并且打印前面的“准备吃包子啦”。 五、迭代器 可以循环的数据类型:list、tuple、dict、set、str、文件和生成器(一种数据结构)。这些可以循环的对象,统称为可迭代对象(Interable)。 判断一个对象是否是可迭代的对象:使用isinstance( [], interable ) from collections import Iterable print(isinstance([],Iterable)) #判断列表是否可迭代,返回True 迭代器:可以被next()函数调用并不断返回下一个值的对象称为迭代器,Iterator。例如生成器是一种迭代器,但迭代器不一定是生成器。文件句柄也是一个迭代器。 from collections import * print(isinstance([],Iterator)) #列表不是迭代器,但是是可迭代对象 print(isinstance( (x*2 for x in range(5)) ,Iterator)) #生成器是迭代器,返回Ture f = open("log.txt","r+",encoding = "utf-8") print(isinstance(f,Iterator)) #文件句柄是迭代器。 使用DIR看方法:如果方法中有__next__()则就是迭代器。 print(dir(x*2 for x in range(5))) #方法中存在__next__(),所以是迭代器 print(dir([])) #[]不是一个迭代器,返回False next([]) #报错TypeError: 'list' object is not an iterator print(dir(dict)) #False print(dir(tuple)) #False print(dir(set)) #False Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()调用,并不断返回下一个数据,直到没有数据抛出StopIteration错误。 Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。 Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。 创建一个Iterator:for循环的底层实际就是用迭代器实现的,高效。 it = iter([1,2,3,4,5]) #创建一个迭代器it while True: try: x = next(it) #使用next获取每一个数据 print(x) except StopIteration as err: break range():在Python3.x中,range()返回一个range对象,该对象是可迭代的,其包含一个迭代器,即ran.__iter__()的返回值。使用该迭代器可以取其中的值。Python2.x中,range()直接返回一个列表,xrange()对应3.x中的range() ran = range(10) ran_iter = ran.__iter__() print(type(ran_iter)) while True: try: print(ran_iter.__next__()) except StopIteration: break 六、内置方法(built-in) all():参数为可迭代对象,例如列表、字典等。当所有的元素都为True则返回True。 print(all([1,2,3,4,5])) #返回True print(all([0,1,2,3,4])) #返回False any():参数为可迭代对象。其中有一个元素为True,则返回True。 print(any([1,2,3,4,5])) #返回True print(any([0,1,2,3,4])) #返回True print(any([0,0,0])) #返回False bin():将整数转换为二进制数。 print(bin(255)) #打印0b11111111 bool():判断真假,0为假,其他数字为真,空列表为假,有元素为真,等等。 bytes():转换为byte。 a = bytes("abcde",encoding="utf-8") print(a) #打印b'abcde' bytearray():转换成byte列表格式。可修改字符。 b = bytearray("abcde",encoding="utf-8") print(b[0]) #打印a的ascii码 97 b[1] = 100 #把b改成d print(b[1]) print(b) #打印bytearray(b'adcde') callable():是否可调用,后面可加()的就算可以调用。 def test(): pass list_test = [1,2,3] print(callable(test)) #函数是可调用的,类也是可调用的 print(callable(list_test)) #列表是不可调用的 chr()和ord():chr将Unicode码转换为字符。ord将字符转换为Unicode码。 print(chr(10000)) #输出✐ print(ord("ぁ")) #输出12353 compile():我们基本用不到,底层用于把代码编译的过程。即代码转成字节码。 code = "for i in range(10):print(i)" #代码是字符串 exe = compile(code , "err.log" , "exec") #将字符串转换为可执行代码 print(exe) #打印<code object <module> at 0x03029128, file "", line 1> exec(exe) #执行代码 code = "print('hello')" eval(code) #eval()也可以执行 这种方式类似实现了import代码然后执行的功能。但是这个函数最牛逼的地方是,可以接受实时传递进去的代码字符串并编译成可执行的代码。那么我们可以让一个函数接受远程传过来的代码,实时执行。 exec直接可以执行字符串代码:(拿compile()来干嘛?) code = "for i in range(10):print(i)" exec(code) dir():查看方法。 d = dict() print(dir(d)) divmod():计算除法,返回商和余数组成的元组。 print(divmod(5,2)) #返回(2,1),2为商,1为余数。 eval():只能处理简单的语句。复杂的用exec() 匿名函数:一个函数只用一次,不会在其他地方调用。则可以定义为匿名函数。 noname = lambda n:print(n) #将匿名函数赋值给变量 noname(5) #使用函数变量调用 匿名函数中不能使用复杂函数语句,例如for循环等。 lambda n:for i in range(10):print(i*n) #错误 filter():用于与lambda函数配合,过滤数据。返回一个迭代器 res = filter(lambda n:n>5,range(10)) #过滤出range(10)中大于5个数,组成列表 for i in res: print(i) 等效于: def file_test(n): #过滤函数 if n > 5: return n res2 = filter(file_test,range(10)) #filter()第一个参数接受一个过滤规则函数,可以是匿名,也可以使普通函数 for i in res2: print(i) map(): res = map(lambda n:n*n,range(10)) #第一个参数是一个处理函数,而不是过滤函数 for i in res: print(i) 相当于: def map_test(n): #处理函数 return n*n res2 = map(map_test,range(10)) for i in res2: print(i) reduce():需要导入functools import functools res = functools.reduce( lambda x,y:x+y,range(10)) print(res) 相当于:即从0加到9。没一次加法结果赋值给x,y为下一个数。 def reduce_test(x,y): return x+y res = functools.reduce(reduce_test,range(10)) print(res) 阶乘: import functools res = functools.reduce( lambda x,y:x*y,range(1,10)) print(res) frozenset():将集合变为不可变集合。 list_test = frozenset([1,2,3,4,5]) globals():返回当前程序里所有全局变量的k-v键值对,包含函数变量。可以用来判断变量存不存在。 name = "Leo" if "name" in globals(): print("变量存在") else: print("变量不存在") hash():中文名---散列。返回一个哈希值。可以使用hash值比较两个对象是否相同。也可以用于二分查找。 print(hash("Leo")) #相同的对象转成hash值是相同的,但每次计算的hash值是不同的 print(hash("Leo")) print(hash("leo")) print(hash("kale")) locals():返回函数内部局部变量。 def test(): name = "Leo" print(name) if "name" in locals(): print("存在") test() max()和min():返回列表、元组、字典(key)、集合或多个参数中的最大值和最小值。 print(max([1,2,3,4,5,6])) #返回列表中的最大元素 print(min([1,3,2,5,4])) #返回列表中的最小元素 print(max(1,2,3,4)) #返回参数中最大 print(min({1,2,3})) #返回集合中最小元素 next():相当于迭代器iterator.__next__()。 it = iter([1,2,3,4,5,6]) print(next(it)) #获取下一个元素 print(it.__next__()) #同上 oct():将二进制、十进制、十六进制转换为8进制。 print( oct(1122) ) #十进制转换为8进制,返回0o2142 print( oct(0x12AF) ) #16进制转换为8进制,返回0o11257 print(oct(0b1111)) #二进制转八进制0o17 pow():计算一个数的次方。 print(pow(2,8)) #2的8次方,输出256 repr():用字符串表示对象,即把对象转换为字符串。但是无法再转回对象。 def test(): pass print(test) #打印函数变量的地址<function test at 0x006954F8> print(type(repr(test))) #转换为字符串<class 'str'> round():四舍五入。第二个参数表示保留几位小数。 print(round(1.34356,3)) slice():切片。没什么用。 d = range(10) print(d[slice(2,5)]) #打印 range(2, 5) sorted():字典是无序的,可以用sorted排序,返回一个排好序的列表。 dict = {5:2,-5:11,1:42,99:12,12:32,-9:98} print(sorted(dict)) #仅对key进行排序,输出[-9, -5, 1, 5, 12, 99] print(sorted(dict.items())) #对所有字典元素按key排序,每个元素转换成元组。输出[(-9, 98), (-5, 11), (1, 42), (5, 2), (12, 32), (99, 12)] print(sorted(dict.items(), key = lambda x:x[1])) #对所有字段元素按value排序。输出[(5, 2), (-5, 11), (99, 12), (12, 32), (1, 42), (-9, 98)] zip():拉链,即将两个列表元素一一对应组合起来。 a = [1,2,3,4] b = ['a','b','c','d'] for i in zip(a,b): #zip(a,b)返回一个迭代器 print(i) #打印结果(1,'a') (2,'b') (3,'c') (4,'d') a = [1,2,3,4,5,6] #如果两个列表元素数量不一致,则按少的那个合并。 b = ['a','b','c','d'] for i in zip(a,b): print(i) #打印结果(1,'a') (2,'b') (3,'c') (4,'d') __import__():只知道一个模块名的字符串,如果import,使用__import__()。用于动态导入。 __import__('my_module')
import本质上是调用__import__()来动态导入模块的
例如:
import os os = __import__("os")七、JSON序列化 将一个对象保存到硬盘中。例如一个字典: import json dict = {"name":"Leo","age":32} f = open("JSON_test","w") f.write(json.dumps(dict)) #序列化 f.close() import json f = open("JSON_test","r") dict = json.loads(f.read()) #反序列化 print(dict["age"]) f.close()
JSON只能处理简单的数据类型,字典、列表、字符串等等。 主要用于不同语言之间进行数据交互。 不同语言中的类、函数等都是不一样的,所以默认只支持简单的。 XML逐步被JSON取代。 八、pickle序列化 使用方法和JSON一样,但是可以处理复杂数据。例如函数等。 import pickle def test_func(): print("Hello") f = open("JSON_test","wb") f.write(pickle.dumps(test_func)) #看似序列化的函数地址,实际上只是函数名称和参数 f.close()import pickle def test_func(): #反序列化这边的程序必须有名字一样,参数一样的函数存在。否则报错 print("Hello1") print("hello2") f = open("JSON_test","rb") func = pickle.loads(f.read()) func() #只要名称和参数与序列化的函数一致,则可以正常运行 f.close()
九、dumps和dump、loads和load的区别 import pickle def test_func(): print("Hello") f = open("JSON_test","wb") pickle.dump(test_func,f) #同f.write(pickle.dumps(test_func)) f.close()import pickle def test_func(): print("Hello1") print("hello2") f = open("JSON_test","rb") func = pickle.load(f) #同func = pickle.loads(f.read()) func() f.close()
注意:同一个数据可以dumps很多次,但都是在一行中连续写入的。loads的时候会报错。所以建议一次dumps对应一次loads。类似虚拟机的快照,每个快照单独存一个文件。 十、软件目录结构规范 Foo/ #项目名 |--bin/ #运行文件目录 | |--foo.py #foo用于运行程序,调用core/下的main.py | |--conf/ #配置文件目录 | |--settings.py #配置文件 | |--logs/ #日志目录 | |--core/ #主程序目录,名字自定义,可以叫core | |--tests/ #测试程序目录 | | |--__init__.py | | |--test_main.py | | | |--__init__.py #包里默认有该文件,文件为空,创建一个包,会自动创建该文件 | |--main.py #程序入口 | |--docs/ #文档目录 | |-conf.py | |--abc.rst | |--setup.py #安装脚本 |--requirements.txt #依赖,例如需要依赖django、mysql |--README #程序描述
README文件: 软件定位,软件的基本功能运行代码的方法:安装环境、启动命令等。简要的使用说明。代码目录结构说明,更详细点可以说明软件的基本原理。常见问题说明 setup.py: 一般来说,用setup.py来管理代码的打包、安装、部署问题。业界标准是使用Python流行的打包工具setuptools来管理这些事情。可以打包成pip能够安装的python程序包。 requirements.txt: 方便开发者维护软件的包依赖。将开发过程中新增的包增加进这个列表汇总,避免的setup.py安装依赖时漏掉软件包。方便读者明确项目使用了哪些Python包。这个文件的格式是每一行包含一个包依赖的说明,通常是flask>=0.10这种格式,要求是这个格式能够pip识别,这样就可以简单的同构pip install -r requirements.txt来把所有Python需要的包依赖都安装好。 import其他目录的模块: 例如,bin/下的foo.py要导入core/main.py。 import os #导入os模块 import sys #导入sys模块 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #动态获取项目目录的绝对路径 sys.path.append(BASE_DIR) #将项目目录的绝对路径加入到系统变量中 from core import main #即可导入core目录下的main.py main.login() #执行main模块中的入口函数
其中 os.path.dirname 是获取上一级目录的绝对路径。
转载于:https://www.cnblogs.com/leokale-zz/p/7600503.html
相关资源:垃圾分类数据集及代码