1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736
| 掘墓人的小铲子 https://juemuren4449.com/categories http://www.webhuang.cn/ https://www.cnblogs.com/wongbingming/p/9028851.html https://www.bbsmax.com/R/E35pMOEydv/ --------------------------------------------------------------------------------------------------- 集合:在我的世界里,你就是唯一 >>>numl={} >>>type(numl) <class 'dict> >>num2={1,2,3,4,5} >>>type(num2) <class'set>
你们确实没有眼花,在Python3里,如果用大括号括起一堆数字但没有体现映射关系,那么Python就会认为这堆玩意儿就是个集合. 好,说回主题,集合在Python中几乎起到的所有作用就是两个字:唯一.举个例子: >>>num={1,2,3,4,5,4,3,2,1} >>>num {1,2,3,4,5} 大家看到,我们根本不需要做什么,集合就会帮我们把重复的数据清理掉,这样是不是很方便呢?但要注意的是,集合是无序的,也就是你不能试图去索引集合中的某一个元素: >>>num[2] Traceback(most recent call last): File"<pyshel1#81>",1ine 1,in<module> num[2] TypeError:'set'object does not support indexing --------------------------------------------------------------------------------------------------- 创建集合 创建集合有两种方法:一种是直接把一堆元素用大括号({})括起来;另一种是用set()。 >>>set1={"小甲鱼","小鱿鱼","小护士","小甲鱼"} >>>set2=set(["小甲鱼","小鱿鱼","小护士","小甲鱼"]) >>>set1==set2 True 现在要求去除列表[1,2,3,4,5,5,3,1,0]中重复的元素.如果还没有学习过集合,你可能会这么写: >>>1ist1=[1,2,3,4,5,5,3,1,0] >>temp=list1[:] >>list1.clear() >>>for each in temp: if each not in list1: 1ist1.append(each) >>>list1 [1,2,3,4,5,0] 当你学习了集合之后,就可以这么干: >>>list1=[1,2,3,4,5,5,3,1,0] >>>list1=list(set(list1)) >>>list1 [0,1,2,3,4,5]
看,知识才是第一生产力!不过大家发现没有?由于set()创造了的集合内部是无序的,所以再调用list()将无序的集合转换成列表就不能保证原来的列表的顺序了(这里Python好心办坏事儿,把0放到前边了),所以如果关注列表中元素的前后顺序问题,使用set()这个函数时就要提高警惕啦! --------------------------------------------------------------------------------------------------- 访问集合 由于集合中的元素是无序的,所以并不能像序列那样用下标来进行访问,但是可以使用代把集合中的数据一个个读取出来: >>> set1 ={1, 2, 3, 4, 5, 4, 3, 2, 1, 0} >> for each in setl: print(each, end ='') 0 1 2 3 4 5
当然也可以使用in和not in判断一个元素是否在集合中已经存在: >>0 in setl True >> 'oo' in set1 False >>>'xx' not in set1 True
使用add()方法可以为集合添加元素,使用remove()方法可以删除集合中已知的元素: >set1.add(6) >> set1 (0, 1, 2, 3, 4, 5, 6} >> set1.remove(5) >> set1 {0, 1, 2, 3, 4, 6}
--------------------------------------------------------------------------------------------------- 不可变集合 有些时候希望集合中的数据具有稳定性,也就是说,像元组一样不能随意地增加或删除集合中的元素.那么我们可以定义不可变集合,这里使用的是frozenset()函数,没错,就是把元素给frozen(冰冻)起来: >>>set1 = frozenset({1,2,3,4,5}) >> set1.add(6) Traceback(most recent call last): File"<pyshell#112>",1ine 1,in <module> set1.add(6) AttributeError:'frozenset'obiect has no attribute'add --------------------------------------------------------------------------------------------------- 永久存储 在你编写代码的时候,操作系统为了更快地做出啊应,把所有当前时数据都放在内存中,因为内存和CPU数据传输的速度要比在硬盘和CPU之间传输的速度快很多倍. 但内存有一个天生的不足,就是一旦断电就没戏,所以小甲鱼在这里再一次呼吁广大未来即将成为伟大程序员的读者们:请养成一个优雅的习惯,随时使用快捷键Ctrl+S保存你的数据. 由于Windows是以扩展名来指出文件是什么类型,所以相信很多习惯使用Windows的朋友很快就反应过来了,.exe是可执行文件格式,,txt是文本文件,.ppt是PowerPoint的专用格式 所有这些都称为文件. --------------------------------------------------------------------------------------------------- 打开文件 在Python 中,使用open()这个函数来打开文件并返回文件对象:open(file,mode ='r',buffering =-1,encoding = None,errors = None,newline = None,closefd =True,opener = None) open()这个函数有很多参数,但作为初学者的我们,只需要先关注第一个和第二个参数即可.第一个参数是传入的文件名,如果只有文件名,不带路径的话,那么Python会在当前文件夹中去找到该文件并打开.
有的读者可能会问:如果我要打开的文件事实上并不存在呢? 那就要看第二个参数了,第二个参数指定文件打开模式 打开模式 执行操作 'r' 以只读方式打开文件(默认) 'w' 以写入的方式打开文件,会覆盖已存在的文件 'x' 如果文件已经存在,使用此模式打开将引发异常 'a' 以写入模式打开,如果文件存在,则在末尾追加写入 'b' 以二进制模式打开文件 't' 以文本模式打开(默认) '+' 可读写模式(可添加到其他模式中使用) 'U' 通用换行符支持
使用open()成功打开一个文件之后,它会返回一个文件对象,拿到这个文件对象,就可以读取或修改这个文件: >>#先将record.txt文件放到Python的根目录下(如C:\Python34) >> f=open("record.txt") 没有消息就是好消息,说明我们的文件成功被打开了. --------------------------------------------------------------------------------------------------- 文件对象的方法 表8-2文件对象方法 文件对象的方法 执行操作 closeC) 关闭文件 read(size=-1) 从文件读取size个字符,当未给定size或给定负值的时候,读取剩余的所有字符,然后作为字符申返回 readlin 以写人模式打开,如果文件存在,则在末尾追加写入 write(str) 将字符串str写入文件 writelines(seq) 向文件写入字符串序列seq,seq应该是一个返回字符串的可迭代对象 seek(offset,from) 在文件中移动文件指针,从from(0代表文件起始位置,1代表当前位置,2代表文件末尾)偏移offset个字节 tell() 返回当前在文件中的位置 --------------------------------------------------------------------------------------------------- 文件的关闭 Python拥有垃圾收集机制,会在文件对象的引用计数降至零的时候自动关闭文件,所以在Python编程里,如果忘记关闭文件并不会造成内存泄露那么危险的结果.
但并不是说就可以不要关闭文件,如果你对文件进行了写入操作,那么应该在完成写入之后关闭文件.因为Python可能会缓存你写入的数据,如果中途发生类似断电之类的事故,那些缓存的数据根本就不会写入到文件中.所以,为了安全起见,要养成使用完文件后立刻关闭的好习惯
--------------------------------------------------------------------------------------------------- 文件的读取和定位 文件的读取方法很多,可以使用文件对象的read()和readline()方法,也可以直接list(f)或者直接使用迭代来读取。read()是按字节为单位读取,如果不设置参数,那么会全部读取出来,文件指针指向文件末尾。tell()方法可以告诉你当前文件指针的位置: >>> f.read() '小客服:小甲鱼,有个好评很好笑哈.\n小甲鱼:哦?\n小客服:"有了小甲鱼,以后妈妈再也不用担心我的学习了~"\n小甲鱼:哈哈哈,我看到啊,我还发微博了呢~\n小客服:嗯嗯,我看了你的微博r~\n小甲鱼:OK~\n小客服:那个有条回复"左手拿着小甲鱼,右手拿着打火机,哪里不会点哪里,so easy^"\n小甲鱼:TT'
>>> f.tell() 284
刚才提到的文件指针是啥?你可以认为它是一个"书签",起到定位的作用。使用seek()方法可以调整文件指针的位置。 seek(offset,from)方法有两个参数,表示从from(0代表文件起始位置,1代表当前位置,2代表文件末尾)偏移offset字节。因此将文件指针设置到文件起始位置,使用seek(0,0)即可: >>> f.tell() 284 >>> f.seek(0,0) 0 >>> f.read(5) '小客服:小' >>> f.tell() 9 (注:因为1个中文字符占用2个字节的空间,所以4个中文加1个英文冒号刚好到位置9。)
readline()方法用于在文件中读取一整行,就是从文件指针的位置向后读取,直到遇到换行符(\n)结束: >>>f.readline() '甲鱼,有个好评很好笑哈.\n'
此前介绍过列表的强大,说什么都可以往里放,这不,也可以把整个文件的内容放到列表中: >>> list(f) ['小甲鱼:哦?\n',小客服:"有了小甲鱼,以后妈妈再也不用担心我的学习了~"\n','小甲鱼:哈哈哈,我看到叮,我还发微博了呢~\n',,小客服:嗯嗯,我看了你的微博r~\n',,小甲鱼:OK~\n',小客服那个有条回复"左手拿着小甲鱼,右手拿着打火机,哪里不会点哪里,so easy ~-"\n','小甲鱼:TT']
对于迭代读取文本文件中的每一行,有些读者可能会这么写: >>> f.seek(0,0) 0 >> lines = 1ist(f) >> for each line in lines: print(each line) 这样写并没有错,但给人的感觉就像是你拿酒精灯去烧开水,水是烧得开,不过效率不是很高.因为文件对象自身是支持迭代的,所以没必要绕圈子,直接使用for语句把内容迭代读取出来即可: >>> f.seek(0,0) 0 >>> for each_line in f: print(each_line) --------------------------------------------------------------------------------------------------- 文件的写入 如果需要写入文件,请确保之前的打开模式有'w'或'a',否则会出错: >>>f = open("record.txt") >>>f.write("这是一段待写人的数据") Traceback(most recent call last): File"< pyshell#135 >",line 1,in <module> f.write("这是一段待写人的数据") io.UnsupportedOperation:not writable >> f.close() >>> f = open("record.txt","w") >> f.writel("这是一段待写人的数据") 10 >>> f.close()
然而一定要小心的是:使用,w'模式写入文件,此前的文件内容会被全部删除! 如果要在原来的内容上追加,一定要使用'a'模式打开文件哦
--------------------------------------------------------------------------------------------------- 一个任务 本节要求读者朋友独立来完成一个任务-将文件(record2.txt)中的数据进行分割并按照以下规则保存起来: (1)将小甲鱼的对话单独保存为boy-*.txt的文件(去掉"小甲鱼:"). (2)将小客服的对话单独保存为girl-*.txt的文件(去掉"小客服:"). (3)文件中总共有三段对话,分别保存为boy_1.txt,girl_1.txt,boy_2.txt,girl_2.txt,boy_3.txt,girl_3.txt共6个文件(提示:文件中不同的对话间已经使用"====================================="分割)。 大家一定要自己先动动手再参考答案: #p8-1.py count =1 boy = [] girl = [] f = open('record.txt') for each_line in f: if each_line[:6] != '== == ==': (role, line_spoken) = each_line.split(':', 1) if role =='小甲鱼': boy. append(line_spoken) if role = '小客服': girl. append(line_spoken) else: file_name_boy = 'boy_' + str(count) + '.txt' file_name_girl = 'girl_' + str(count) + '.txt' boy_file = open(file_name_boy, 'w') girl_file = open(file_name girl, 'w') boy_file.writelines ( boy) girl_file.writelines(girl) boy =[] girl =[] count += 1 file_name_boy = "boy_' + str(count) + '.txt file_name_girl = 'girl_'+ str(count)+ '.txt boy_file =open(file_name_boy, 'w') girl_file = open(file_name_girl, 'w') boy_file.writelines(boy) girl_file.writelines(girl) boy_file.close() girl_file.close()
事实上可以利用函数封装得更好看一些: #p82.py def save_file(boy,girl,count): file_name_boy ='boy'+ str(count) + '.txt file_name_girl ='girl'+ str(count) + '.txt' boy_file = open(file_name_boy,'w') girl_file = open(file_name-girl,'w') boy_file.writelines(boy) girl_file.writelines(girl) boy_file.close() girl_file.close()
def split_file(file_name): count = 1 boy =[] girl =[] f= open(file_name) for each_line in f: if each_line[:6] != '== == ==': (role,line_spoken)= each_line.split(':',1) if role == '小甲鱼': boy.append(line_spoken) if role =='小客服': girl.append(line_spoken) else: save_file(boy,girl,count) boy =[] girl =[] count += 1 save_file(boy,girl,count) f.close() split file('record.txt')
--------------------------------------------------------------------------------------------------- 文件系统:介绍一个高大上的东西 模块是什么?其实我们写的每一个源代码文件(*.py)都是一个模块。Python自身带有非常多实用的模块,在日常编程中,如果能够熟练地掌握它们,将事半功倍 比如刚开始介绍的文字小游戏,里边就用random模块的randint()函数来生成随机数. 然而要使用这个randint()函数,直接就调用可不行: >>random.randint(0,9) Traceback(most recent call last): File"<pyshell#140>",line 1,in <module> random.randint(0,9) NameError:name'random'is not defined 正确的做法应该是先使用import语句导入模块,然后再使用: >> import random >> random.randint(0,9) 3 >> random.randint(0,9) 1 >> random.randint(0,9) 8 首先要介绍的是高大上的OS模块,OS就是Operating System的缩写,意思是操作系统,之所以说OS模块高大上,是因为对于文件系统的访问,Python一般是通过OS模块来实现的.我们所知道常用的操作系统就有Windows,Mac OS,Linux,UNIX等,这些操作系统底层对于文件系统的访问工作原理是不一样的,因此你可能就要针对不同的系统来考虑使用哪些文件系统模块…这样的做法是非常不友好且麻烦的,因为这意味着当你的程序运行环境一旦改变,你就要相应地去修改大量的代码来应付.
但是Python是跨平台的语言,也就是说,同样的源代码在不同的操作系统不需要修改就可以同样实现.有了OS模块,不需要关心什么操作系统下使用什么模块,OS模块会帮你选择正确的模块并调用。
表8-3 Os模块中关于文件/目录常用的函数使用方法 函数名 使用方法 getcwd() 返回当前工作目录 chdir(path) 改变工作目录 listdir(path='.') 列举指定目录中的文件名(.'表示当前目录,'.'表示上一级目录) mkdir(path) 创建单层目录,如该目录已存在抛出异常 makedirs(path) 递归创建多层目录,如果该目录已存在则抛出异常,注意:'E:\allb和'E:\allc'并不会冲突 remove(path) 删除文件 rmdir(path) 删除单层目录,如果该目录非空则抛出异常 removedirs(path) 递归删除目录,从子目录到父目录逐层尝试删除,遇到目录非空则抛出异常 rename(old,new) 将文件old重命名为new system(command) 运行系统的shell命令 以下是支持路径操作中常用到的一些定义,支持所有平台 os.curdir 指代当前目录('.') os.pardir 指代上一级目录(..') os.sep 输出操作系统特定的路径分隔符(在Windows下为',Linux下为'/1) os.linesep 当前平台使用的行终止符(在Windows下为"\rn',Linux下为"\n') os.name 指代当前使用的操作系统(包括,posix','nt','mac','os2','ce','java') --------------------------------------------------------------------------------------------------- getcwd() 在有些情况下我们需要获得应用程序当前的工作目录(比如要保存临时文件),那么可以使用getcwd()函数获得: >>>import os >>>os.getcwd() 'C:\\Fython34' --------------------------------------------------------------------------------------------------- chdir(path) 用chdir()函数可以改变当前工作目录,比如可以切换到E盘: >>>os.chdir("E:\\") >>> os.getcwd() "E:\\" --------------------------------------------------------------------------------------------------- listdir(path='.') 有时候你可能需要知道当前目录下有哪些文件和子目录,那么listdir()函数可以帮你列举出来。path参数用于指定列举的目录,默认值是'.',代表根目录,也可以使用'..'代表上一层目录: >>> os.listdir() ['$ RECYCLE.BIN','Arduino','Systen Volume Information','工作室,'工具箱,'鱼c光盘','鱼c工作室编程教学'] >>> os.listdir("C:\\") ['$ 360Section','s Recycle.Bin',"360SANDBOX','Boot','bootmgr','BOOTNXT,'DRHyperbootSync 'Documents and Settings','hiberfil.sys','Intel','iSee','mfg','MSOCache','OneDriveT'emp'pagefile.sys','PerfLogs','Program Files','Program Files(x86)','ProgramData'.'Python27',"Python34','Recovery','Recovery.txt','swapfile.sys','System Volume Information','Userst',"Windows']
2020/3/10 --------------------------------------------------------------------------------------------------- 4.mkdir(path) mkdir()函数用于创建文件夹,如果该文件夹存在,则抛出FileExistsError异常: >> os.mkdir("test") >>> os.listdir() ['$ RECYCLE.BIN','Arduino','System Volume Information','test','工作室','工具箱','鱼c光盘','鱼C工作室编程教学'] >> os.mkdir("test") Traceback(most recent call last): File"<pyshell#156>",line 1,in <module> os.mkdir("test") FileExistsError:[WinError 183]当文件已存在时,无法创建该文件.:'test'
--------------------------------------------------------------------------------------------------- 5.makedirs(path) makedirs()函数可以用于创建多层目录: >> os.makedirs(r".\a\b\c") --------------------------------------------------------------------------------------------------- 6.remove(path)、rmdir(path)和removedirs(path) remove()函数用于删除指定的文件,注意是删除文件,不是删除目录.如果要删除目录,则用rmdir()函数;如果要删除多层目录,则用removedirs()函数. >> os.listdir() ['a',"b','test.txt'] >>>#当前工作目录结构为a\b\c,b\,test.txt >> os.remove("test.txt") >> os.rmdir("b") >> os.removedirs(r"a\b\c") >>> os.listdir() []
--------------------------------------------------------------------------------------------------- 7.rename(old,new) rename()函数用于重命名文件或文件夹: >>> os.listdir() ['a','a.txt'] >>> os.rename("a","b") >> os.rename("a.txt","b.txt") > os.listdir() ['b','b.txt'] --------------------------------------------------------------------------------------------------- 8.system(command) 几乎每个操作系统都会提供一些小工具,system()函数用于使用这些小工具: >> os.systen("calc")#calc是Windows系统自带的计算器回车后即弹出计算器 --------------------------------------------------------------------------------------------------- 9.walk(top) 最后是walk()函数,这个函数在有些时候确实非常有用,可以省去你很多麻烦.该函娄的作用是遍历top参数指定路径下的所有子目录,并将结果返回一个三元组(路径,[包含目录],[包含文件]),来看下面的例子: >> for i in os.walk("test"): print(i) ("test',['a','b','c',[]) ('test\\a',[],['a.txt']) ('test\\b',['bl','b2'],['b.txt']) ("test\\b\\b1',[],['bl.txt']) ('test\\b\\b2',[],['b2.txt']) ('test\\c',['cl'], []) ('test\\c\\cl',['c11'], []) ('test\\c\\cl\\cll',[],['c11.txt'])
另外path模块还提供了一些很实用的定义,分别是:os.curdir表示当前目录;os.pardir表示上一级目录('..');os.sep表示路径的分隔符,比如Windows系统下为'\\',Linux下为'/';os.linesep表示当前平台使用的行终止符(在Windows下为'\r\n',Linux下为'\n');os.name表示当前使用的操作系统. 另一个强大的模块是os.path,它可以完成一些针对路径名的操作.表8-4列举了os.path中常用到的函数使用方法.
表8-4 os.path模块中关于路径常用的函数使用方法 函数名 使用方法 basename(path) 去掉目录路径,单独返回文件名 dirname(path) 去掉文件名,单独返回目录路径 join(path[,path2[,...) 将path1和path2各部分组合成一个路径名 split(path) 分割文件名与路径,返回(f-path,f-name)元组.如果完全使用目录,它也会将最后一个目录作为文件名分离,且不会判断文件或者目录是否存在 plitext(path) 分离文件名与扩展名,返回(f-name,f-extension)元组 getsize(file) 返回指定文件的尺寸,单位是字节 getatime(file) 返回指定文件最近的访问时间(浮点型秒数,可用time模块的gmtime()或localtime()函数换算) getctime(file) 返回指定文件的创建时间(浮点型秒数,可用time模块的gmtime()或localtime()函数换算) getmtime(file) 返回指定文件最新的修改时间(浮点型秒数,可用time模块的gmtime()或localtime()函数换算) 以下为函数返回True或False exists(path) 判断指定路径(目录或文件)是否存在 isabs(path) 判断指定路径是否为绝对路径 isdir(path) 判断指定路径是否存在且是一个目录 isfile(path) 判断指定路径是否存在且是一个文件 islink(path) 判断指定路径是否存在且是一个符号链接 smount(path) 判断指定路径是否存在且是一个挂载点 samefile(pathl,path2) 判断path1和path2两个路径是否指向同一个文件 --------------------------------------------------------------------------------------------------- 10.basename(path)和dirname(path) basename()和dirname()函数分别用于获得文件名和路径名: >> os.path.dirname(r"a\b\test.txt") 'a\\b' >> os.path.basename(r"a\b\text.txt") 'text.txt' --------------------------------------------------------------------------------------------------- 11.join(path1[,path2[,...]]) join()函数跟BIF的那个join()函数不同,os.path.join()是用于将路径名和文件名组合成一个完整的路径: >>>os.path.join(r"C:\Python34\Test","FishC.txt") "C:\\Python34\\Test\\FishC.txt' --------------------------------------------------------------------------------------------------- 12.split(path)和splitext(path) split()和splitext()函数都用于分割路径,split()函数分割路径和文件名(如果完全使用目录,它也会将最后一个目录作为文件名分离,且不会判断文件或者目录是否存在);splitext()函数则是用于分割文件名和扩展名: >>>os.path.split(r"a\b\test.txt") ('a\\b','test.txt') >>>os.path.splitext(r"a\b\test.txt") ('a\\b\test','.txt') --------------------------------------------------------------------------------------------------- 13.getsize(file) getsize()函数用于获取文件的尺寸,返回值是以字节为单位: >>> os.chdir(r"C:\Python34") >> os.path.getsize("python.exe") 40960 --------------------------------------------------------------------------------------------------- 14.getatime(file)、getctime(file)和getmtime(file) getatime()、getctime()和getmtime()分别用于获得文件的最近访问时间、创建时间和修改时间.不过返回值是浮点型秒数,可用time模块的gmtime()或localtime()函数换算: >>>import time >>>temp= time.localtime(os.path.getatime("python.exe")) >>> print("python.exe被访问的时间是:",time.strftime("%d %b %Y %H:%M:%S",temp)) python.exe被访问的时间是:27 May 2015 21:16:59 >> temp= time.localtime(os.path.getctime("python.exe")) >>> print("python.exe被创建的时间是:",time.strftime("%d %b %Y %H: %M :%S",temp)) python.exe被创建的时间是:24 Feb 2015 22:44:44 >> temp = time.localtime(os,path.getmtime("python.exe")) >>> print("python.exe被修改的时间是:",time.strftime("%d %b %Y %H: %M :%S",temp))
python.exe被修改的时间是:24 Feb 2015 22:44:44 还有一些函数返回布尔类型的值,具体的解释见表8-4,这里就不一一举例了
--------------------------------------------------------------------------------------------------- pickle:腌制一缸美味的泡菜 从一个文件里读取字符串非常简单,但如果想要读取出数值,那就需要多费点儿周折.因为无论是read()方法,还是readline()方法,都是返回一个字符串,如果希望从字符串里边提取出数值的话,可以使用int()函数或float()函数把类似123或'3.14'这类字符串强制转换为具体的数值.
此前一直在讲保存文本,然而当要保存的数据像列表、字典甚至是类的实例这些更复杂的数据类型时,普通的文件操作就会变得不知所措.也许你会把这些都转换为字符串,再写入到一个文本文件中保存起来,但是很快你就会发现要把这个过程反过来,从文本文件恢复数据对象,就变得异常麻烦了.
所幸的是,Python提供了一个标准模块,使用这个模块,就可以非常容易地将列表、字典这类复杂数据类型存储为文件了.这个模块就是本节要介绍的pickle模块. pickle就是泡菜,腌菜的意思,相信很多女读者都对韩国泡菜尤其情有独钟.至于Python的作者为何把这么一个高大上模块命名为泡菜,我想应该是跟韩剧脱不了干系. 好,说回这个泡菜.用官方文档中的话说,这是一个令人惊叹(amazing)的模块,它几乎可以把所有Python的对象都转化为二进制的形式存放,这个过程称为pickling,那么从二进制形式转换回对象的过程称为unpickling. 说了这么多,还是来点干货吧: --------------------------------------------------------------------------------------------------- 说了这么,还是来点干货吧: #pe83.py import pickle my_list=[123,3.14,'小甲鱼,['another list']] pickle_file = open('E:\\my_list.pkl','wb') pickle.dump(my_list,pickle_file) pickle_file.close() 分析一下:这里希望把这个列表永久保存起来(保存成文件),打开的文件一定要以二进制的形式打开,后缀名倒是可以随意,不过既然是使用pickle保存,为了今后容易记忆,建议还是使用.pkl或.pickle,使用dump方法来保存数据,完成后记得保存,跟操作普通文本文件一样. 程序执行之后E盘会出现一个my_list.pkl的文件,用记事本打开之后显示乱码(因为它保存的是二进制形式),如图8-5所示. 那么在使用的时候只需用二进制模式先把文件打开,然后用load把数据加载进来: #p84. py import pickle pickle_file = open("E:\\my_list.pkl","rb") my_list = pickle.load(pickle_file) print(my_list)
程序执行后又取回我们的列表啦: >>> [123,3.14,'小甲鱼',['another list']] >>> 利用pickle模块,不仅可以保存列表,事实上pickle可以保存任何你能想象得到的东西.
--------------------------------------------------------------------------------------------------- 异常处理 你不可能总是对的:程序出现逻辑错误或者用户输入不合法都会引发异常,但这些异常并不是致命的,不会导致程序崩溃死掉.可以利用Python提供的异常处理机制,在异常出现的时候及时捕获,并从内部自我消化掉. 那么什么是异常呢?举个例子: #p9_1.py file-name = input('请输入要打开的文件名:') f = open(file_name,'r') print('文件的内容是:') for each_line in f: print(each_line)
这里当然假设用户的输入是正确的,但只要用户输入一个不存在的文件名,那么上面的代码就不堪一击: >>> 请输入要打开的文件名:我为什么是一个文档.txt Traceback(most recent call last): File"E:\p9_1.py",line 2,in <module> f = open(file_name,'r') FileNotFoundError:[Errno 2]No such file or directory:'我为什么是一个文档.txt' 上面的例子就抛出了一个FileNotFoundError异常
--------------------------------------------------------------------------------------------------- 1.AssertionError:断言语句(assert)失败 大家还记得断言语句吧?在关于分支和循环的章节里讲过。当assert这个关键字后边的条件为假的时候,程序将停止并抛出AssertionError异常。assert语句一般是在测试程序的时候用于在代码中置入检查点: >>my_list =["小甲鱼"] >> assert len(my_list)>0 >> my_list.pop() '小甲鱼' >> assert len(my_list) >0 Traceback(most recent call last): File"< pyshell#3>",line 1,in <module> assert len(my_list)>0 AssertionError --------------------------------------------------------------------------------------------------- 2.AttributeError:尝试访问未知的对象属性 当试图访问的对象属性不存在时抛出的异常: >>> my_list =[] >>> my_list.fishc Traceback(most recent call last): File"< pyshell#5>",line 1,in <module > my list.fishc AttributeError:'list'object has no attribute'fishc' --------------------------------------------------------------------------------------------------- 3.IndexError:索引超出序列的范围在使用序列的时候就常常会遇到IndexError异常,原因是索引超出序列范围的内容: >>> my list=[1,2,3] >>> my list[3] Traceback(most recent call last): File"<pyshell#7>",line 1,in <module> my list[3] IndexError:list index out of range --------------------------------------------------------------------------------------------------- 4.KeyError:字典中查找一个不存在的关键字 当试图在字典中查找一个不存在的关键字时就会引发KeyError异常,因此建议使用dict.get()方法: >> my_dict ={"one":1,"two":2,"three":3} >>> my_dict["one"] 1 >>ny dict["four"] Traceback(most recent call last): File"<pyshell#10>",line 1,in <module> my_dict["four"] KeyError:'four --------------------------------------------------------------------------------------------------- 5.NameError:尝试访问一个不存在的变量 当尝试访问一个不存在的变量时,Python会抛出NameError异常: >> fishc Traceback (most recent call last): File "< pyshell#11>", line 1, in <module> fishc NameError: name 'fishc' is not defined --------------------------------------------------------------------------------------------------- 6.OSError:操作系统产生的异常 OSError顾名思义就是操作系统产生的异常,像打开一个不存在的文件会引发FileNotFoundError,而这个FileNotFoundError就是OSError的子类.例子上面已经演示过,这里就不再重复. --------------------------------------------------------------------------------------------------- 7.SyntaxError:Python的语法错误 如果遇到SyntaxError是Python的语法错误,这时Python的代码并不能继续执行,你应该先找到并改正错误: >>> print "I love fishc.com" SyntaxRrror:Missing parentheses in call to'print' --------------------------------------------------------------------------------------------------- 8.TypeError:不同类型间的无效操作 有些类型不同是不能相互进行计算的,否则会抛出TypeError异常: >>>>1 + "1" Traceback(most recent call last): File"<pyshell#15>",line 1,in <module> 1 + "1" TypeError:unsupported operand type(s) for +:'int' and 'str'
--------------------------------------------------------------------------------------------------- 9.ZeroDivisionError:除数为零 地球人都知道除数不能为零,所以除以零就会引发ZeroDivisionError异常: >>>5 / 0 Traceback(most recent call last): File"<pyshell#16>",line 1,in <module> 5/0 ZeroDivisionError:division by zero 好了,知道程序抛出异常就说明这个程序有问题,但问题并不致命,所以可以通过捕获这些异常,并纠正这些错误就行.那应该如何捕获和处理异常呢? 异常捕获可以使用try语句来实现,任何出现在try语句范围内的异常都会被及时捕获到.try语句有两种实现形式:一种是try-except,另一种是try-finally.
--------------------------------------------------------------------------------------------------- try-except语句 try-except 语句格式如下: try: 检测范围 except Exception[as reason]: 出现异常(Exception)后的处理代码
try-except语句用于检测和处理异常,举个例子来说明这一切是如何工作的: #p92.py f = open('我为什么是一个文档.txt') print(f.read()) f.close()
以上代码在"我为什么是一个文档.txt"这个文档不存在的时候,Python就会报错说文件不存在: >>> Traceback(most recent call last): File"E:\p92.py",line 1,in <module> f= open('我为什么是一个文档.txt') FileNotFoundError:[Errno 2]No such file or directory:'我为什么是一个文档.txt' >>> 显然这样的用户体验不好,因此可以这么修改: #p93.py try: f= open('我为什么是一个文档.txt') print(f.read()) f.close() except OSError: print('文件打开的过程中出错啦TT')
上面的例子由于使用了大家习惯的语言来表述错误信息,用户体验当然会好很多: >>> 文件打开的过程中出错啦TT >>>
但是从程序员的角度来看,导致OSError异常的原因有很多(例如FileExistsError、FileNotFoundError,PermissionError等等),所以可能会更在意错误的具体内容,这里可以使用as把具体的错误信息给打印出来: except OSError as reason: print('文件出错啦T-TYn错误原因是:'+ str(reason)) --------------------------------------------------------------------------------------------------- 针对不同异常设置多个except 一个try语句还可以和多个except语句搭配,分别对感兴趣的异常进行检测处理: #p94.py try: sum =1 + '1' f-= open('我是一个不存在的文档.txt") print(f.read()) f.close() except OSError as reason: print('文件出错啦T_T\n错误原因是:'+ str(reason)) except TypeError as reason: print('类型出错啦T_T\n错误原因是:'+ str(reason)) --------------------------------------------------------------------------------------------------- 对多个异常统一处理 except后边还可以跟多个异常,然后对这些异常进行统一的处理: #p9_5.py try: int('abe') sum =1 +"11 f = open('我是一个不存在的文档.txt') print(f.read()) f.close() except(OSError,TypeError): print('出错啦T_T\n错误原因是:'+ str(reason)) --------------------------------------------------------------------------------------------------- 9.2.3捕获所有异常 如果你无法确定要对哪一类异常进行处理,只是希望在try语句块里一旦出现任何异常,可以给用户一个"看得懂"的提醒,那么可以这么做 ... except: print('出错啦~') ... 不过通常不建议你这么做,因为它会隐藏所有程序员未想到并且未做好处理准备的错误,例如当用户输入Ctrl+C试图终止程序,却被解释为KeyboardInterrupt异常.另外要注意的是,try语句检测范围内一旦出现异常,剩下的语句将不会被执行。 --------------------------------------------------------------------------------------------------- try-finally语句 如果"我是一个不存在的文档"确实存在,open()函数正常返回文件对象,但异常却发生在成功打开文件后的sum=1 +'1',语句上.此时Python将直接跳到except语句,也就是说,文件打开了,但并没有执行关闭文件的命令: #p96.py try: f=open('我是一个不存在的文档.txt') print(f.read()) sum =1 + '1' f.close() except: print('出错啦') 为了实现像这种"就算出现异常,但也不得不执行的收尾工作(比如在程序崩溃前保存用户文档)",引人了finally来扩展try: #p9_7.py try: f=open('我是一个不存在的文档.txt') print(f.read()) sum =1 + '1' except: print('出错啦') finally: f.close() 如果try语句块中没有出现任何运行时错误,会跳过except语句块执行finally语句块的内容.如果出现异常,则会先执行except语句块的内容再执行finally语句块的内容.总之finally语句块中的内容就是确保无论如何都将被执行的内容. --------------------------------------------------------------------------------------------------- raise语句 有读者可能会问,我的代码能不能自己抛出一个异常呢?答案是可以的,你可以使月raise语句抛出一个异常: >> raise ZeroDivisionError Traceback(most recent call last): File"<pyshell#0>",line 1,in <module> raise ZeroDivisionError ZeroDivisionError 抛出的异常还可以带参数,表示异常的解释: >> raise ZeroDivisionError("除数不能为零!") Traceback(most recent call last): File"<pyshell#2>",line 1,in <module> raise ZeroDivisionError("除数不能为零!") ZeroDivisionError:除数不能为零! --------------------------------------------------------------------------------------------------- 丰富的else语句 在Python里,else语句的功能更加丰富。 在Python中,else语句不仅能跟if语句搭,构成"要么怎样,要么不怎样"的句式; 它还能跟循环语句(for语句或者while语句),构成"干完了能怎样,干不完就别想怎样"的句式; 其实else语句还能够跟刚刚讲的异常处理进行搭配,构成"没有问题?那就干吧"的句式,下边逐个给大家解释。 --------------------------------------------------------------------------------------------------- 1.要么怎样,要么不怎样 典型的if-else搭配: if条件: 条件为真执行 else: 条件为假执行 --------------------------------------------------------------------------------------------------- 2.干完了能怎样,干不完就别想怎样 else可以跟for和while循环语句配合使用,但else语句块只在循环完成后执行,也就是说,如果循环中间使用break语句跳出循环,那么else里边的内容就不会被执行了.举个例子: #p9_8.py def showMaxFactor (num): count =num//2 while count > 1: if num count == 0: print('%d最大的约数是%d' % (num, count)) break count-=1 else: print('%d是素数!' % num) num = int(input('请输入一个数:')) showlaxFactor (num) 这个小程序主要是求用户输入的数的最大约数,如果是素数的话就顺便提醒"这是一个素数".注意要使用地板除法(count=num//2)哦,否则结果会出错.使用暴力的方法一个个尝试(num%count ==0),如果符合条件则打印出最大的约数,并break,同时不会执行else语句块的内容了.但如果一直没有遇到合适的条件,则会执行else语句块内容. for语句的用法跟while一样,这里就不重复举例了. ------------------------------------------------------------------------------------- 3.没有问题?那就干吧 else语句还能跟刚刚学的异常处理进行搭配,实现跟与循环语句搭配差不多:只要tryi句块里没有出现任何异常,那么就会执行else语句块里的内容啦。举个例子: #p99.py try: int ('abc') except ValueError as reason: print('出错啦:' + str(reason)) else: print('没有任何异常!') ------------------------------------------------------------------------------------- 简洁的with语句 有读者可能觉着打开文件又要关闭文件,还要关注异常处理有点烦人,所以Python提了一个with语句,利用这个语句抽象出文件操作中频繁使用的try/except/finally相关的细节。对文件操作使用with语句,将大大减少代码量,而且你再也不用担心出现文件打开了记关闭的问题了(with会自动帮你关闭文件)。举个例子: #p9_10. рy try: f = open( 'data.txt', 'w') for each_line in f: print(each_line) except OSError as reason: print('出错啦:' + str(reason)) finally: f.close()
使用with语句,可以改成这样: #p9-11.py try: with open('data.txt','w') as f: for each_line in f: print(each_line) except OSError as reason: print('出错啦:' +str(reason))
有了with语句,就再也不用担心忘记关闭文件了。
|