鱼C论坛

 找回密码
 立即注册
查看: 2813|回复: 15

[学习笔记] 【Pyhon 029讲心得体会】【 分割小甲鱼和小客服对话】

[复制链接]
发表于 2018-11-24 19:30:22 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 heidern0612 于 2018-12-17 10:05 编辑

写的个人心得都是个人思考、猜测、臆断的过程,有错误难免,恳请广大鱼油给予指正。



这一讲比较难,其实很多方法都学过,但是不知道怎么用,看答案的时候恍然大悟,啊,原来这个还可以这么用。

所以学习有的时候是理论有了,动手比较少。有的时候理解艰难涩会的时候,就是敲代码敲的少了。

任何时候或者任何情况下的不理解、学的不好,都是因为代码敲的少。

但简洁也很重要,还是老师的那句话:Don't repeat yourself

以下部分文字摘自网络,只为个人学习使用,不用于任何商业用途。


1、老师视频里的疑问:

小甲鱼老师没有仔细的讲视频里最后(在封装函数之前),

为什么要复制添加创建文件的那步给全局变量里,难道只复制创建文件这一步就可以创建文件了吗?(只复制了for语句里else那一步)

分裂文件的依据呢? 上面虽然有分裂文件的依据,但是for循环好像都循环完了啊?

哎?好像似乎没循环完哈, 第三段对话开始的时候,似乎也进入了for循环的else语句,但是没有else判断了(因为else判断是==六个“=”号),

这里就是小甲鱼老师为什么只复制了下面一段else,没有复制上面if的缘故,因为if判断完了,文件也分裂完了,但是else不符合的情况下,自然就跳到下面的语句了。

其实还有个笨方法:不是靠"======"判断吗?那就在老师视频里txt文件的最尾部再多加一行"======",就不用那么多判断了 ,哈哈。


不废话,上代码分析:

  1. #打开record.txt文件
  2. f = open('E:\\record.txt')  

  3. #定义3个变量,并对它们初始化
  4. boy = []     
  5. girl = []
  6. count = 1

  7. #循环读取文件
  8. for each_line in f:
  9.   
  10.   #如果当前内容不等于"======",则继续读取内容;否则读取,开始写操作
  11.   if each_line[:6] != "======":            
  12.    
  13.     #读取的内容以":"进行分割,分割后分别赋值给元组元素role和spoken
  14.     (role,spoken) = each_line.split(':',1)
  15.    
  16.     #如果对话角色为"小甲鱼",则将文件追加到boy列表中
  17.     if role == '小甲鱼':                  
  18.        boy.append(spoken)
  19.       
  20.     #如果对话角色为"小客服",则将文件追加到girl列表中
  21.     if role == '小客服':                  
  22.        girl.append(spoken)
  23.   else:
  24.      #定义输出文件名称
  25.      file_name_boy = 'boy_'+str(count)+'.txt'  
  26.      file_name_girl = 'girl_'+str(count)+'.txt'
  27.    
  28.      #打开文件
  29.      boy_file = open(file_name_boy,'w')         
  30.      girl_file = open(file_name_girl,'w')     
  31.      
  32.      #writelines的参数是序列(比如列表),它会迭代帮你写入文件。
  33.      boy_file.writelines(boy)     
  34.      girl_file.writelines(girl)
  35.      
  36.      #关闭文件对象
  37.      boy_file.close()                                   
  38.      girl_file.close()                          
  39.      
  40.      #当前写操作完毕后,必须进行初始化操作,以准备下一个的写入操作
  41.      boy = []
  42.      girl = []
  43.      count += 1

  44. #因为第三段对话的结尾没有"===",所以需要再次进行上面的重复写操作,保存第三段对话
  45. #定义输出文件名称     
  46. file_name_boy = 'boy_'+str(count)+'.txt'  
  47. file_name_girl = 'girl'+str(count)+'.txt'  

  48. #打开文件   
  49. boy_file = open(file_name_boy,'w')         
  50. girl_file = open(file_name_girl,'w')

  51. #writelines的参数是序列(比如列表),它会迭代帮你写入文件。     
  52. boy_file.writelines(boy)   
  53. girl_file.writelines(girl)

  54. #关闭文件对象      
  55. boy_file.close()                                
  56. girl_file.close()                    

  57. #关闭文件对象
  58. f.close()
复制代码




定义函数之后的过程:


  1. #定义一个保存文件的方法
  2. def save_file(boy,girl,count):
  3.     #定义输出文件名称
  4.     file_name_boy = 'boy_' + str(count) + '.txt'
  5.     file_name_girl = 'girl_' + str(count) + '.txt'
  6.     #打开文件
  7.     boy_file = open('E:\\%s'%file_name_boy,'w')
  8.     girl_file = open('E:\\%s'%file_name_girl,'w')
  9.     #writelines的参数是序列(比如列表),它会迭代帮你写入文件
  10.     boy_file.writelines(boy)
  11.     girl_file.writelines(girl)
  12.     #关闭文件对象
  13.     boy_file.close()
  14.     girl_file.close()
  15. #定义一个读取和分割文件内容的方法
  16. def split_file(file_name):
  17.     f = open('E:\\record.txt')
  18.     #定义3个变量,并对它们初始化
  19.     boy = []
  20.     girl = []
  21.     count = 1
  22.     #循环读取文件
  23.     for each_line in f:
  24.         #如果当前内容不等于“======”,则读取内容分割;否则分类保存文件
  25.         if each_line[:6] != '======':
  26.             #读取的内容以“:”进行分割,分割后分别赋值给role和line_spoken
  27.             (role,line_spoken) = each_line.split(':',1)
  28.             #按对话角色分别把spoken追加到不同的表中
  29.             if role == '小甲鱼':
  30.                 boy.append(line_spoken)
  31.             if role == '小客服':
  32.                 girl.append(line_spoken)
  33.         else:
  34.             #保存文件
  35.             save_file(boy,girl,count)
  36.             #保存文件后,再初始化变量
  37.             count += 1
  38.             boy = []
  39.             girl = []
  40.     #因为第三段对话的结尾没有"===",所以需要再调用save_file方法,保存第三段对话
  41.     save_file(boy,girl,count)
  42.     f.close()
  43. #主方法:只要调用split_file就可以完成所有的操作
  44. split_file('E:\\record.txt')
复制代码


这就是我说的,小积木成大擎天柱啊~  封装之后清爽了许多。




分析动动手答案:




0.编写一个程序,接受用户的输入并保存为新的文件:

先输入文件名,然后打开文件,调用write将输入的字符串写入文件中,以:w作为写完标识符,写完之后调用close函数即完成文件的写入。

  1. def filewrite(file_name):
  2.      print('请输入内容【单独输入‘:w’保存退出】:')
  3.      f=open(file_name,'w')
  4.      while True:
  5.           a=input()
  6.           if a!=':w':
  7.               f.write('%s'% a)
  8.           else:
  9.                break

  10.      f.close()

  11. file_name=input('请输入文件名:')   
  12. filewrite(file_name)
复制代码




1.编写一个程序比较用户输入的两个文件,如果不同,显示出所有不同处的行号与第一个不同字符的位置:
  1. def compare(fname1,fname2):        #这里定义的文件名,就是下面用户交互时输入的文件名,当然能在python目录下最好,不能的话,就得带上路径。
  2.     f1 = open(fname1)                                #只读模式默认打开
  3.     f2 = open(fname2)
  4.     count = 0                                                #统计行数
  5.     differ = []                                                #统计不一样的数量
  6.     for line1 in f1:
  7.         line2 = f2.readline()
  8.         count += 1                                        #随着行数的变化,count也跟着变化
  9.         if line1 != line2:                                        #2者不相同的话,differ列表就append一个值,假定循环到第二行不相同,就添加一个2的数字元素进differ列表。
  10.             differ.append(count)

  11.     f1.close()
  12.     f2.close()
  13.     return differ                                                #把differ列表返给函数。

  14. fname1 = input('请输入需要比较的头一个文件名:')
  15. fname2 = input('请输入需要比较的另一个文件名:')

  16. differ = compare(fname1,fname2)

  17. lenth = len(differ)
  18. if len(differ) == 0:                                #如果上面compare函数中differ返回的是个空列表,判断两个文件相同。
  19.                                                         #注:*这里的differ指的是函数compare内部的differ,不是外部被赋值给compare函数的全局变量differ。
  20.                                                         #实际上,截止到上面那个函数定义完毕后,再出现的differ已经是个新的变量,不是原先的那个differ了。

  21.     print('两个文件完全一样!')
  22. else:
  23.     print('两个文件共有%d处不同'%len(differ))                                        #这里几处不同len的是differ列表的长度。
  24.     for each in differ:
  25.         print('第%d行不一样'%each)                                                        #这里each代表是differ列表里每一个元素的值。
复制代码




3.编写一个程序,当用户输入文件名和行数(N)后,将该文件的前N行内容打印到屏幕上:
  1. def file_view(file_name,line_nun):
  2.     print('\n文件%s的前%s的内容如下:\n'%(file_name,line_num))
  3.     f = open(file_name)                                #打开用户input输入的文件名
  4.     for i in range(int(line_num)):                       
  5.         print(f.readline(),end='')                        #注意这里调用的readline,而不是readline的复数形式readlines,所以这里打开的都是单行。
  6.                                                                 #结合上面的for循环以及range范围,这里打开的依次就是range范围的文件单行。

  7.     f.close()

  8. file_name = input(r'请输入要打开的文件(如C:\\test.txt):')
  9. line_num = input('请输入需要显示该文件前几行:')
  10. file_view(file_name,line_num)
复制代码



评分

参与人数 1荣誉 +4 鱼币 +1 贡献 +2 收起 理由
想跳的鱼 + 4 + 1 + 2

查看全部评分

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-12-4 19:35:35 | 显示全部楼层
谢谢分享
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-12-4 20:12:31 | 显示全部楼层
谢谢分享
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-2-2 21:25:17 | 显示全部楼层
请问下,第1题第22行代码,您注释写的是:这里的differ不是被compare赋值了的全局变量differ,也就是说这里的differ不是那个:differ = file_compare。但我搞不懂的是,def file_name里的differ,不是函数内部的局域变量吗?怎么可以在外面调用的呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-2-2 21:53:28 | 显示全部楼层
来论坛学潮汕话 发表于 2019-2-2 21:25
请问下,第1题第22行代码,您注释写的是:这里的differ不是被compare赋值了的全局变量differ,也就是说这里 ...

名字是一样的,虽然内容也一样,但不是一个类型。

你可以看到定义的主函数返回的值是函数内部变量differ这个列表。

外面实例化函数后,实例化的名字也叫differ(其实就是重新赋值了下实例化,函数返回的结果还是内部那个列表)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-2-3 19:08:44 | 显示全部楼层
heidern0612 发表于 2019-2-2 21:53
名字是一样的,虽然内容也一样,但不是一个类型。

你可以看到定义的主函数返回的值是函数内部变量diff ...

明白了,也就是说不是调用局部变量differ,而是外部重新被赋值了的differ,只不过他们的结果是一样的,所以,如果compare函数中的differ返回的是个空列表,那么外部变量的differ也是个空列表
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-2-3 19:40:00 | 显示全部楼层
来论坛学潮汕话 发表于 2019-2-3 19:08
明白了,也就是说不是调用局部变量differ,而是外部重新被赋值了的differ,只不过他们的结果是一样的,所 ...

是的,是这个意思。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-12-8 22:16:54 | 显示全部楼层
楼主,求解。基本每一个课后习题我都需要看答案才有思路,当时看完后可以写出来,并且也看得懂是什么意思,但是过了2天又忘记了。有什么比较好的方法么
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-12-9 17:41:37 | 显示全部楼层
xxwoaini897 发表于 2019-12-8 22:16
楼主,求解。基本每一个课后习题我都需要看答案才有思路,当时看完后可以写出来,并且也看得懂是什么意思, ...

多看多练。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-12-10 00:17:01 | 显示全部楼层
新手有一个疑问:
#读取的内容以":"进行分割,分割后分别赋值给元组元素role和spoken
    (role,spoken) = each_line.split(':',1)
在进行分割的时候,分割成两部分,为什么后一部分是到换行符为止的?(文件read()出来实际是有换行符的对吧?)这是一个默认吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-12-10 09:53:08 | 显示全部楼层
落舞千秋 发表于 2019-12-10 00:17
新手有一个疑问:
#读取的内容以":"进行分割,分割后分别赋值给元组元素role和spoken
    (role,spoken) ...

(role,spoken) = each_line.split(':',1)

role和spoken之间以冒号“:”为分割换行。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-12-10 12:04:02 | 显示全部楼层
本帖最后由 落舞千秋 于 2019-12-10 14:14 编辑

谢谢,中午的时候打了一大堆发现又不对,全部删掉再来提问:
  1. f= open('D:\\record.txt')
  2. s = f.read()

  3. for i in s:
  4.     if i[:6] != '======':
  5.         (a,b)=i.split(':',1)
  6.         print((a,b))
复制代码


这样的话为何又会报错说值不足够分成2份?
#Traceback (most recent call last):
  File "C:/Users/xxx/Desktop/2.py", line 6, in <module>
    (a,b)=i.split(':',1)
ValueError: not enough values to unpack (expected 2, got 1)#
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-12-10 14:49:30 | 显示全部楼层
落舞千秋 发表于 2019-12-10 12:04
谢谢,中午的时候打了一大堆发现又不对,全部删掉再来提问:

检查中英文是否混用。

代码和txt文档都检查下。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-12-10 21:46:10 | 显示全部楼层
heidern0612 发表于 2019-12-10 14:49
检查中英文是否混用。

代码和txt文档都检查下。

在别的帖子中找到了答案(是对象的问题),原来是文本文件是根据文本行来进行迭代的,所以可以这样分隔并换行,而我的s是字符串,是以单个字符进行迭代的,所以无法进行上面那样的分隔,也感谢大大的回复帮助
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-10-10 17:20:01 | 显示全部楼层
  1.   for line1 in f1:
  2.         line2 = f2.readline()
  3.         count += 1                                        #随着行数的变化,count也跟着变化
  4.         if line1 != line2:                                        #2者不相同的话,differ列表就append一个值,假定循环到第二行不相同,就添加一个2的数字元素进differ列表。
  5.             differ.append(count)
复制代码

请问for line1 in f1是对文件的f1遍历进行循环,这是按f1中的每个字符还是每行字符进行遍历?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-10-12 14:25:33 | 显示全部楼层
一条咸鱼fish 发表于 2020-10-10 17:20
请问for line1 in f1是对文件的f1遍历进行循环,这是按f1中的每个字符还是每行字符进行遍历?

f1是打开的文件,for循环遍历的是每一行。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-20 13:14

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表