Python循环语句,对象

  1. 案例1:斐波那契数列
  2. 案例2:模拟cp操作
  3. 案例3:生成8位随机密码

1 案例1:斐波那契数列

1.1 问题

编写fib.py脚本,主要要求如下:

  • 输出具有10个数字的斐波那契数列
  • 使用for循环和range函数完成
  • 改进程序,要求用户输入一个数字,可以生成用户需要长度的斐波那契数列

1.2 方案

斐波那契数列就是某一个数,总是前两个数之和,比如0,1,1,2,3,5,8。由于输出是一串数字,可以用列表的结构存储。开始时,列表中有两个值,即0,1。然后通过循环向列表中追加元素,追加元素总是列表中最后两个元素值之和。

本例使用的是列表,不能使用元组,因为列表是一个可变类型,而元组是不可变类型。各种数据类型的比较如下:

按存储模型分类

标量类型:数值、字符串

容器类型:列表、元组、字典

按更新模型分类:

可变类型:列表、字典

不可变类型:数字、字符串、元组

按访问模型分类

直接访问:数字

顺序访问:字符串、列表、元组

映射访问:字典

由于循环次数是确定的,可以使用for循环。python中的for循环与传统的for循环(计数器循环)不太一样,它更象shell脚本里的foreach迭代。python中的for接受可迭代对象(例如序列或迭代器)作为其参数,每次迭代其中一个元素。

for循环经常与range()函数一起使用。range函数语法如下:

  1. range([start,] stop[, step])

range函数将返回一个列表,如果列表没有给定起始值,那么起始值从0开始,结束值是给定的结束值的前一个值,另外还可以设置步长值。例:

  1. >>> range(10)            #没有给定起始值则从0开始,结束值为9
  2. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  3. >>> range(5,10)      #给定起始值,列表的第一个值就是给定的起始值
  4. [5, 6, 7, 8, 9]
  5. >>> range(0, 10, 2)  #给定步长值为2,列出10以内的偶数
  6. [0, 2, 4, 6, 8]
  7. >>> range(1, 10, 2)  #给定起始值、步长值,列出10以内的奇数
  8. [1, 3, 5, 7, 9]

当将脚本改成交互式运行时,需要注意,用户输入的数字,python仍然将其视为字符而不是整型数字,需要使用int()将用户输入做类型转换。

在进行运算时,应使得参与运算的对象属于同一类型,否则如果python无法进行隐匿类型转换将会出现异常。

  1. >>> '30' + 3
  2. Traceback (most recent call last):
  3. File "<stdin>", line 1, in <module>
  4. TypeError: cannot concatenate 'str' and 'int' objects

上面的代码之所以出现错误,是因为不能将字符串与数字进行加法或拼接运算。如果希望将其拼接,可以使用下面的方式:

  1. >>> '30' + str(3)
  2. '303'

如果希望将其全作为数字进行相加,可以使用下面的方式:

  1. >>> int('30') + 3
  2. 33

1.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:编写固定输出的斐波那契数列

  1. [root@py01 bin]# vim fibs.py
  2. #!/usr/bin/env python
  3. fibs = [0, 1]
  4. for i in range(8):
  5. fibs.append(fibs[-1] + fibs[-2])
  6. print fibs

执行结果如下:

  1. [root@py01 bin]# ./fibs.py
  2. [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

步骤二:将脚本改为交互式执行

如果希望生成用户指定个数的数列,需要与用户进行交互,通过raw_input()函数读取用户指定的长度。因为raw_input()函数读入的数据均为字符串,所以需要对其进行类型转换,通过int()函数将字符串类型的数值转换成数字类型。

为了能够进行加法计算,需要提前拥有两个数值。既然已经存在两个值,那么用户指定数列个数后,在循环时,应该少循环两次。

修改后的代码如下:

  1. [root@py01 bin]# vim fibs2.py
  2. #!/usr/bin/env python
  3. fibs = [0, 1]
  4. nums = int(raw_input('Input a number: '))
  5. for i in range(nums - 2):
  6. fibs.append(fibs[-1] + fibs[-2])
  7. print fibs

脚本运行结果如下:

  1. [root@py01 bin]# ./fibs2.py
  2. Input a number: 5
  3. [0, 1, 1, 2, 3]
  4. [root@py01 bin]# ./fibs2.py
  5. Input a number: 20
  6. [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]

案例2:模拟cp操作

2.1 问题

编写cp.py脚本,实现以下目标:

  1. 将/bin/ls“拷贝”到/root/目录下
  2. 要求读取/bin/ls后,每次读取4096字节,依次写入到新文件
  3. 不要修改原始文件

2.2 方案

“拷贝”一个文件,可以想像成谅是先在目标位置创建一个空文件,然后再将源文件读出,写入到新文件中。

在python中打开文件的方法是open(),或者使用file(),两个函数完全一样可以进行相互替换。open的语法如下:

  1. open(name[, mode[, buffering]])

open的第一个参数是文件名,可以是相对路径,也可以是绝路径。最后的一个参数是缓冲设置,默认情况下使用缓冲区。硬盘是计算机系统中最慢的一个组件,如果每产生一个字符都立即写入磁盘,那么这种方式的工作效率将极其低下,可以先把数据放在内存的缓冲区中,当缓冲区的数据比较多的时候,再批量写入磁盘文件。当文件关闭的时候,缓冲区的数据也会写入磁盘。第二个模式参数的含义如下:

  1. >>> f = open('abc.txt', 'r')        #文件不存在
  2. Traceback (most recent call last):
  3. File "<stdin>", line 1, in <module>
  4. IOError: [Errno 2] No such file or directory: 'abc.txt'
  5. >>> f = open('/etc/hosts')
  6. >>> f.write('hello')    #写入文件时报错,因为并非以写入方式打开
  7. Traceback (most recent call last):
  8. File "<stdin>", line 1, in <module>
  9. IOError: File not open for writing
  10. >>> f = open('abc.txt', 'w')   #文件不存在,首先创建了abc.txt
  11. >>> f.read()                    #因为以写的方式打开,读取时出错
  12. Traceback (most recent call last):
  13. File "<stdin>", line 1, in <module>
  14. IOError: File not open for reading

打开文件时并不消耗太多内存,但是将文件内容读到变量中,会根据读入的数据大小消耗相应的内存。例:

  1. #首先创建一个名为ttt.img的文件,大小为100MB
  2. [root@py01 bin]# dd if=/dev/zero of=ttt.img bs=1M count=100
  3. [root@py01 bin]# free –m   #观察已用内存,值为665M
  4. total       used       free     shared    buffers     cached
  5. Mem:        994        665        329          0         24        339
  6. -/+ buffers/cache:        301        693
  7. Swap:         4031          0       4031
  8. [root@py01 bin]# python   #从另一终端中打开python解释器
  9. Python 2.6.6 (r266:84292, Oct 12 2012, 14:23:48)
  10. [GCC 4.4.6 20120305 (Red Hat 4.4.6-4)] on linux2
  11. Type "help", "copyright", "credits" or "license" for more information.
  12. >>> f = open('ttt.img')   #打开该文件
  13. [root@py01 bin]# free –m  #观察已用内存并没有变化
  14. total       used       free     shared    buffers     cached
  15. Mem:        994        665        329          0         24        339
  16. -/+ buffers/cache:        301        693
  17. Swap:         4031          0       4031
  18. >>> data = f.read()    #再回到python解释器,读入全部文件内容
  19. [root@py01 bin]# free –m   #观察已用内存,增加了100MB
  20. total       used       free     shared    buffers     cached
  21. Mem:        994        764        230          0         24        339
  22. -/+ buffers/cache:        399        595
  23. Swap:         4031          0       4031
  24. >>> del data  #回到python解释器,删除data变量
  25. [root@py01 bin]# free –m  #已用内存又减少了100MB
  26. total       used       free     shared    buffers     cached
  27. Mem:       994        663        330          0         24        339
  28. -/+ buffers/cache:        299        695
  29. Swap:         4031          0       4031

为了防止一次性读入大文件消耗太多的内存,可以采用循环的方式,多次少量读取数据。一般情况下可以设置每次读取4096字节即可。

2.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:编写脚本

注意,通常文件操作有三个步骤:打开文件,处理文件,关闭文件。往往被忽略的是关闭文件,如果文件没有正常关闭,有可能造成数据丢失。

  1. [root@py01 bin]# vim cp.py
  2. #!/usr/bin/env python
  3. dstfile = '/root/ls'
  4. srcfile = '/bin/ls'
  5. oldf = open(srcfile)             #以读方式打开老文件
  6. newf = open(dstfile, 'w')       #以写方式打开新文件
  7. while True:                       #因为不确定要循环多少次,设置条件永远为真
  8. data = oldf.read(4096)       #每次只读入4096字节
  9. if len(data) == 0:           #如果文件已经全部读取完毕则中断循环
  10. break
  11. newf.write(data)
  12. oldf.close()
  13. newf.close()

步骤二:通过md5值判断新老文件是否完全一致

  1. [root@py01 bin]# ./cp.py
  2. [root@py01 bin]# md5sum /root/ls
  3. c98cff985579da387db6a2367439690a  /root/ls
  4. [root@py01 bin]# md5sum /bin/ls
  5. c98cff985579da387db6a2367439690a  /bin/ls
  6. [root@py01 bin]# ll /root/ls
  7. -rw-r--r--. 1 root root 117024 Jun 27 15:40 /root/ls
  8. [root@py01 bin]# chmod +x /root/ls
  9. [root@py01 bin]# /root/ls /home/
  10. demo  demo.tar.gz    lost+found

md5值是文件的指纹信息,如果两个文件的内容完全一样,那么其md5值一定相同,如果两个文件有微小的不同,其md5值也一定完全不一样。不过文件的权限不会影响md5值的判定。将拷贝后的目标文件加上执行权限,就可以像原始文件一样的工作了。


案例3:生成8位随机密码

3.1 问题

编写randpass.py脚本,实现以下目标:

  • 使用random的choice函数随机取出字符
  • 用于密码的字符通过string模块获得
  • 改进程序,用户可以自己决定生成多少位的密码

3.2 方案

假定只使用大小写字母和数字作为密码,这些字符可以自己定义,不过string模块中已有这些属性。通过导入string模块可以减少代码量,同时提高效率。

  1. >>> import string
  2. >>> string.lowercase
  3. 'abcdefghijklmnopqrstuvwxyz'
  4. >>> string.uppercase
  5. 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  6. >>> string.letters
  7. 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
  8. >>> string.digits
  9. '0123456789'

这个程序的主要思路是,首先创建一个空字符串变量用于存储密码,然后每次在可用字符中随机选择一个字符,再把该字符与变量中的字符进行拼接。

3.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:编写脚本,生成8位随机密码

  1. [root@py01 bin]# vim randpass.py
  2. #!/usr/bin/env python
  3. import string
  4. import random
  5. passwd = ''
  6. passchs = string.letters + string.digits
  7. for i in range(8):
  8. passwd += random.choice(passchs)
  9. print passwd

脚本运行结果如下:

  1. [root@py01 bin]# ./randpass.py
  2. 1U4MMBg3
  3. [root@py01 bin]# ./randpass.py
  4. ExvoT8Hi

步骤二:改进脚本,生成指定位数的随机密码

上面程序的主要问题是,第一,生成的密码倍数是固定的,如果希望生成其他倍数的密码,还需要重新改写代码;第二,如果生成密码这个功能在其他地方也需要使用,那么代码的重用性得不到体现。

改进的代码可以解以上两个问题,具体如下:

  1. [root@py01 bin]# vim randpass2.py
  2. #!/usr/bin/env python
  3. import string
  4. import random
  5. allchs = string.letters + string.digits
  6. def genPwd(num = 8):
  7. pwd = ''
  8. for i in range(num):
  9. pwd += random.choice(allchs)
  10. return pwd
  11. if __name__ == '__main__':
  12. print genPwd()
  13. print genPwd(6)

代码执行结果如下:

  1. [root@py01 bin]# ./randpass2.py
  2. hUEDcvmc
  3. RgNMhu
  4. [root@py01 bin]# ./randpass2.py
  5. s9Ojwpp7
  6. 70BOsU
  7. [root@py01 bin]# python
  8. Python 2.6.6 (r266:84292, Oct 12 2012, 14:23:48)
  9. [GCC 4.4.6 20120305 (Red Hat 4.4.6-4)] on linux2
  10. Type "help", "copyright", "credits" or "license" for more information.
  11. >>> import randpass2
  12. >>> randpass2.genPwd(10)   #在其他位置也可以直接调用randpass2模中的函数
  13. 'WobDgiHsC8'

Python循环语句,对象的更多相关文章

  1. python 循环语句 函数 模块

    python循环语句 while循环语法结构 当需要语句不断的重复执行时,可以使用while循环 while expression: while_suite 语句ehile_suite会被连续不断的循 ...

  2. jmeter数据库,charles抓包,Python循环语句

    jmeter数据库,charles抓包,Python循环语句 一.Jemeter数据库 添加jar包数据库 jemeter=>浏览 添加JDBC Connection Configuration ...

  3. python循环语句详细讲解

    想必大家都知道python循环语句吧,可以python循环语句有多种,比如for循环.while循环.if.else等等,   我们可以通过设置条件表达式永远不为 false 来实现无限循环,实例如下 ...

  4. Python 循环语句(break和continue)

    Python 循环语句(break和continue) while 语句时还有另外两个重要的命令 continue,break 来跳过循环,continue 用于跳过该次循环,break 则是用于退出 ...

  5. Python循环语句代码详解:while、for、break

    1 while循环 循环语句是程序设计中常用的语句之一.任何编程语言都有while循环,Python也不例外.while循环的格式如下所示.  while(表达式):       -   else:  ...

  6. Python循环语句

    1.Python循环类型 1.while循环:在某条件下,循环执行某段程序 a. while语句有两个重要命令:continue,break来跳出循环. continue用来跳出该次循环 break用 ...

  7. Python系列之 - python循环语句

    前两篇说的是数据类型和数据运算,本篇来讲讲条件语句和循环语句. 1. 条件语句 条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块. 可以通过下图来简单了解条件语句的执 ...

  8. Python循环语句之break与continue的用法

    摘自原文章: http://www.jb51.net/article/73383.htm Python break 语句Python break语句,就像在C语言中,打破了最小封闭for或while循 ...

  9. Python循环语句及函数的定义

      循环语句¶ 重复执行某一个固定的动作或者任务 语法 for 变量 in序列: 语句1 语句2 ..... In [2]: # 列表知识只是以后会讲 # 比如[1,2,3,4,5,6,7] list ...

随机推荐

  1. 有了这套微信小程序x5调试,调试一些简单的开发者工具调试不了的功能不成问题!!!!

    1.首先我们需要打开微信 TBS 调试 地址是:http://debugx5.qq.com 2.然后打开手机 打开开发者模式,打开 USB 调试 3.然后 在谷歌浏览器地址栏输入 chrome://i ...

  2. 前后端分离基于Oauth2的SSO单点登录怎样做?

    一.说明 单点登录顾名思义就是在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统,免除多次登录的烦恼:本文主要介绍跨域间的 前后端分离 项目怎样实现单点登录,并且与 非前后端分离 的差 ...

  3. JVM笔记-垃圾收集算法与垃圾收集器

    1. 一些概念 1.1 垃圾&垃圾收集 垃圾:在 JVM 语境下,"垃圾"指的是死亡的对象所占据的堆空间. 垃圾收集:所谓"垃圾收集",就是将已分配出去 ...

  4. Hadoop集群搭建(二)~centos6.8的安装

    这篇记录在创建好的虚拟机中安装centos6.8 1,在虚拟机界面-选择编辑虚拟机设置 2,CD/DVD,选择使用ISO映像文件,找到安装包的位置,确定 3,回到虚拟机的界面,开启此虚拟机 4,安装 ...

  5. 使用Github Packages功能上传nuget包到Github

    前几天微软收购npm的新闻对于软粉来收很是振奋.微软收购npm很可能是为了加强Github Packages.目前Github,Typescript,VSCode,npm这些开源社区的重磅工具全部都在 ...

  6. Java 注解简介

    一,什么叫注解 用一个词就可以描述注解,那就是元数据,即一种描述数据的数据.所以,可以说注解就是源代码的元数据.比如,下面这段代码: 1 2 3 4 @Override public String t ...

  7. MySQL数据备份与恢复(二) -- xtrabackup工具

    上一篇介绍了逻辑备份工具mysqldump,本文将通过应用更为普遍的物理备份工具xtrabackup来演示数据备份及恢复的第二篇内容. 1.  xtrabackup 工具的安装 1.1  安装依赖包 ...

  8. 深入理解JAVA字符串常量池

    初学JAVA时,在学习如何比较两个字符串是否相等,大量资料告诉我,不能用等于号( = )去比较,需要使用equals方法,理由是String是一个对象,等号此时比较的是两个字符串在java内存堆中的地 ...

  9. hdu1213 并查集板子

    题目链接:http://icpc.njust.edu.cn/Problem/Hdu/1213/ 并查集是一种支持合并与查找的数据结构,在森林中进行操作,加上路径压缩,合并和查找的时间复杂度几乎都是常数 ...

  10. 【短道速滑一】OpenCV中cvResize函数使用双线性插值缩小图像到长宽大小一半时速度飞快(比最近邻还快)之异象解析和自我实现。

    今天,一个朋友想使用我的SSE优化Demo里的双线性插值算法,他已经在项目里使用了OpenCV,因此,我就建议他直接使用OpenCV,朋友的程序非常注意效率和实时性(因为是处理视频),因此希望我能测试 ...