Python基础(二):斐波那契数列、模拟cp操作、生成8位随机密码
一、斐波那契数列
目标:
编写fib.py脚本,主要要求如下:
- 输出具有10个数字的斐波那契数列
- 使用for循环和range函数完成
- 改进程序,要求用户输入一个数字,可以生成用户需要长度的斐波那契数列
方案:
斐波那契数列就是某一个数,总是前两个数之和,比如0,1,1,2,3,5,8。由于输出是一串数字,可以用列表的结构存储。开始时,列表中有两个值,即0,1。然后通过循环向列表中追加元素,追加元素总是列表中最后两个元素值之和。
本例使用的是列表,不能使用元组,因为列表是一个可变类型,而元组是不可变类型。各种数据类型的比较如下:
按存储模型分类
标量类型:数值、字符串
容器类型:列表、元组、字典
按更新模型分类:
可变类型:列表、字典
不可变类型:数字、字符串、元组
按访问模型分类
直接访问:数字
顺序访问:字符串、列表、元组
映射访问:字典
由于循环次数是确定的,可以使用for循环。python中的for循环与传统的for循环(计数器循环)不太一样,它更象shell脚本里的foreach迭代。python中的for接受可迭代对象(例如序列或迭代器)作为其参数,每次迭代其中一个元素。
for循环经常与range()函数一起使用。range函数语法如下:
range([start,] stop[, step])
range函数将返回一个列表,如果列表没有给定起始值,那么起始值从0开始,结束值是给定的结束值的前一个值,另外还可以设置步长值。例:
>>> range(10) #没有给定起始值则从0开始,结束值为9
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> range(5,10) #给定起始值,列表的第一个值就是给定的起始值
[5, 6, 7, 8, 9]
>>> range(0, 10, 2) #给定步长值为2,列出10以内的偶数
[0, 2, 4, 6, 8]
>>> range(1, 10, 2) #给定起始值、步长值,列出10以内的奇数
[1, 3, 5, 7, 9]
当将脚本改成交互式运行时,需要注意,用户输入的数字,python仍然将其视为字符而不是整型数字,需要使用int()将用户输入做类型转换。
在进行运算时,应使得参与运算的对象属于同一类型,否则如果python无法进行隐匿类型转换将会出现异常。
>>> '30' + 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects
上面的代码之所以出现错误,是因为不能将字符串与数字进行加法或拼接运算。如果希望将其拼接,可以使用下面的方式:
>>> '30' + str(3)
'303'
如果希望将其全作为数字进行相加,可以使用下面的方式:
>>> int('30') + 3
33
步骤:
步骤一:编写固定输出的斐波那契数列
[root@py01 bin]# vim fibs.py
#!/usr/bin/env python
fibs = [0, 1]
for i in range(8):
fibs.append(fibs[-1] + fibs[-2])
print fibs
执行结果如下:
[root@py01 bin]# ./fibs.py
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
步骤二:将脚本改为交互式执行
如果希望生成用户指定个数的数列,需要与用户进行交互,通过raw_input()函数读取用户指定的长度。因为raw_input()函数读入的数据均为字符串,所以需要对其进行类型转换,通过int()函数将字符串类型的数值转换成数字类型。
为了能够进行加法计算,需要提前拥有两个数值。既然已经存在两个值,那么用户指定数列个数后,在循环时,应该少循环两次。
修改后的代码如下:
[root@py01 bin]# vim fibs2.py
#!/usr/bin/env python
fibs = [0, 1]
nums = int(raw_input('Input a number: '))
for i in range(nums - 2):
fibs.append(fibs[-1] + fibs[-2])
print fibs
脚本运行结果如下:
[root@py01 bin]# ./fibs2.py
Input a number: 5
[0, 1, 1, 2, 3]
[root@py01 bin]# ./fibs2.py
Input a number: 20
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]
附加:查看计算斐波拉契数列的代码:
#!/usr/bin/python
#coding:utf-8
#计算斐波拉契数列的值
x=[0,1]
for i in range(12): //变量i只参与循环次数,不用作计算
tmp=x[-1]+x[-2] //斐波拉契数列规律:后面一个数是前面两数字之和
x.append(tmp) //将计算的值追加进x列表
print x
二、模拟cp操作
目标:
编写cp.py脚本,实现以下目标:
- 将/bin/ls“拷贝”到/root/目录下
- 要求读取/bin/ls后,每次读取4096字节,依次写入到新文件
- 不要修改原始文件
方案:
“拷贝”一个文件,可以想像成谅是先在目标位置创建一个空文件,然后再将源文件读出,写入到新文件中。
在python中打开文件的方法是open(),或者使用file(),两个函数完全一样可以进行相互替换。open的语法如下:
open(name[, mode[, buffering]])
open的第一个参数是文件名,可以是相对路径,也可以是绝路径。最后的一个参数是缓冲设置,默认情况下使用缓冲区。硬盘是计算机系统中最慢的一个组件, 如果每产生一个字符都立即写入磁盘,那么这种方式的工作效率将极其低下,可以先把数据放在内存的缓冲区中,当缓冲区的数据比较多的时候,再批量写入磁盘文 件。当文件关闭的时候,缓冲区的数据也会写入磁盘。第二个模式参数的含义如下:
>>> f = open('abc.txt', 'r') #文件不存在
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 2] No such file or directory: 'abc.txt'
>>> f = open('/etc/hosts')
>>> f.write('hello') #写入文件时报错,因为并非以写入方式打开
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: File not open for writing
>>> f = open('abc.txt', 'w') #文件不存在,首先创建了abc.txt
>>> f.read() #因为以写的方式打开,读取时出错
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: File not open for reading
打开文件时并不消耗太多内存,但是将文件内容读到变量中,会根据读入的数据大小消耗相应的内存。例:
#首先创建一个名为ttt.img的文件,大小为100MB
[root@py01 bin]# dd if=/dev/zero of=ttt.img bs=1M count=100
[root@py01 bin]# free –m #观察已用内存,值为665M
total used free shared buffers cached
Mem: 994 665 329 0 24 339
-/+ buffers/cache: 301 693
Swap: 4031 0 4031
[root@py01 bin]# python #从另一终端中打开python解释器
Python 2.6.6 (r266:84292, Oct 12 2012, 14:23:48)
[GCC 4.4.6 20120305 (Red Hat 4.4.6-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> f = open('ttt.img') #打开该文件
[root@py01 bin]# free –m #观察已用内存并没有变化
total used free shared buffers cached
Mem: 994 665 329 0 24 339
-/+ buffers/cache: 301 693
Swap: 4031 0 4031
>>> data = f.read() #再回到python解释器,读入全部文件内容
[root@py01 bin]# free –m #观察已用内存,增加了100MB
total used free shared buffers cached
Mem: 994 764 230 0 24 339
-/+ buffers/cache: 399 595
Swap: 4031 0 4031
>>> del data #回到python解释器,删除data变量
[root@py01 bin]# free –m #已用内存又减少了100MB
total used free shared buffers cached
Mem: 994 663 330 0 24 339
-/+ buffers/cache: 299 695
Swap: 4031 0 4031
为了防止一次性读入大文件消耗太多的内存,可以采用循环的方式,多次少量读取数据。一般情况下可以设置每次读取4096字节即可。
步骤:
步骤一:编写脚本
注意,通常文件操作有三个步骤:打开文件,处理文件,关闭文件。往往被忽略的是关闭文件,如果文件没有正常关闭,有可能造成数据丢失。
[root@py01 bin]# vim cp.py
#!/usr/bin/env python
dstfile = '/root/ls'
srcfile = '/bin/ls'
oldf = open(srcfile) #以读方式打开老文件
newf = open(dstfile, 'w') #以写方式打开新文件
while True: #因为不确定要循环多少次,设置条件永远为真
data = oldf.read(4096) #每次只读入4096字节
if len(data) == 0: #如果文件已经全部读取完毕则中断循环
break
newf.write(data)
oldf.close()
newf.close()
步骤二:通过md5值判断新老文件是否完全一致
[root@py01 bin]# ./cp.py
[root@py01 bin]# md5sum /root/ls
c98cff985579da387db6a2367439690a /root/ls
[root@py01 bin]# md5sum /bin/ls
c98cff985579da387db6a2367439690a /bin/ls
[root@py01 bin]# ll /root/ls
-rw-r--r--. 1 root root 117024 Jun 27 15:40 /root/ls
[root@py01 bin]# chmod +x /root/ls
[root@py01 bin]# /root/ls /home/
demo demo.tar.gz lost+found
md5值是文件的指纹信息,如果两个文件的内容完全一样,那么其md5值一定相同,如果两个文件有微小的不同,其md5值也一定完全不一样。不过文件的权限不会影响md5值的判定。将拷贝后的目标文件加上执行权限,就可以像原始文件一样的工作了。
三、生成8位随机密码
目标:
编写randpass.py脚本,实现以下目标:
- 使用random的choice函数随机取出字符
- 用于密码的字符通过string模块获得
- 改进程序,用户可以自己决定生成多少位的密码
方案:
假定只使用大小写字母和数字作为密码,这些字符可以自己定义,不过string模块中已有这些属性。通过导入string模块可以减少代码量,同时提高效率。
>>> import string
>>> string.lowercase
'abcdefghijklmnopqrstuvwxyz'
>>> string.uppercase
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.digits
'0123456789'
这个程序的主要思路是,首先创建一个空字符串变量用于存储密码,然后每次在可用字符中随机选择一个字符,再把该字符与变量中的字符进行拼接。
步骤:
步骤一:编写脚本,生成8位随机密码
[root@py01 bin]# vim randpass.py
#!/usr/bin/env python
import string
import random
passwd = ''
passchs = string.letters + string.digits
for i in range(8):
passwd += random.choice(passchs)
print passwd
脚本运行结果如下:
[root@py01 bin]# ./randpass.py
1U4MMBg3
[root@py01 bin]# ./randpass.py
ExvoT8Hi
步骤二:改进脚本,生成指定位数的随机密码
上面程序的主要问题是,第一,生成的密码倍数是固定的,如果希望生成其他倍数的密码,还需要重新改写代码;第二,如果生成密码这个功能在其他地方也需要使用,那么代码的重用性得不到体现。
改进的代码可以解以上两个问题,具体如下:
[root@py01 bin]# vim randpass2.py
#!/usr/bin/env python
import string
import random
allchs = string.letters + string.digits
def genPwd(num = 8):
pwd = ''
for i in range(num):
pwd += random.choice(allchs)
return pwd
if __name__ == '__main__':
print genPwd()
print genPwd(6)
代码执行结果如下:
[root@py01 bin]# ./randpass2.py
hUEDcvmc
RgNMhu
[root@py01 bin]# ./randpass2.py
s9Ojwpp7
70BOsU
[root@py01 bin]# python
Python 2.6.6 (r266:84292, Oct 12 2012, 14:23:48)
[GCC 4.4.6 20120305 (Red Hat 4.4.6-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import randpass2
>>> randpass2.genPwd(10) #在其他位置也可以直接调用randpass2模中的函数
'WobDgiHsC8'
附加:对比shell与python脚本取8位随机密码
##################################################
取8位随机密码
shell脚本:
X=‘’
pass=""
for i in {1..8}
do
n=$[RANDOM%62] #26小写字母+26大写字母+10个数字=62
tmp=${X:$n:1}
pass=${pass}$tmp
done
echo $pass
python脚本:
import string
import random
passwd=''
X=string.letters+string.digits //在终端里面,用help()命令进去查看,查看string
for i in range(8):
tmp=random.choice(X)
passwd+=tmp
print passwd
帮助:
>>>help()
help>string
...
或者:
>>>help('string') //有些系统变量不用加单引,写了也不会错
lowercase -- a string containing all characters considered lowercase letters //小写字母
uppercase -- a string containing all characters considered uppercase letters //大写字母
letters -- a string containing all characters considered letters //大小写字母组合
digits -- a string containing all characters considered decimal digits //数字
###########################################################
写一个cp的函数脚本
#!/usr/bin/python
#coding:utf-8
x=raw_input("源文件名:")
y=raw_input("目标文件名:")
data1=open(x)
data2=open(y,'w')
for i in data1:
data2.writelines(i)
data1.close()
data2.close()
#########################################################
Shell和Python脚本的定义
shell函数
函数名(){
命令
}
函数名 //调用上面的函数
Python如果定义函数
函数名():
命令
函数名() //调用上面的函数
例如:
def jsq(x,y):
print "x+y=",x+y
print "x*y=",x*y
print "x-y=",x-y
jsq(1,2) //调用上面定义的函数结果是:3,2,-1
jsq(2,8) //调用上面定义的函数结果是:10,16,-6
def jsq(x,y=3): //y=3是默认参数,调用时y若没赋值就会用默认值,x和y都可以设置默认值
print "x+y=",x+y
print "x*y=",x*y
print "x-y=",x-y
jsq(2) //调用上面定义的函数结果是:5,6,-1,这里y取了默认值3
jsq(2,8) //调用上面定义的函数结果是:10,16,-6
#########################################################
类似与shell中的$0、$1、$2...
#!/usr/bin/python
#coding:utf-8
import sys //导入sys模块
print sys.argv[0]
print sys.argv[1]
print sys.argv[2]
print sys.argv
[root@WY ~]# ./python1.py a b 1 c 8 //上面的python脚本命名为python1.py,在终端运行该脚本后的结果如下
./python2.py
a
b
['./python2.py', 'a', 'b', '1', 'c', '8']
cp文件的python脚本
#!/usr/bin/python
#coding:utf-8
#拷贝文件的第二中方法
import sys
x=sys.argv[1] //参考上面
y=sys.argv[2]
data1=open(x)
data2=open(y,'w')
for i in data1:
data2.writelines(i)
data1.close()
data2.close()
[root@WY ~]# ./cp.py /etc/passwd /opt/1.txt //复制前一个文件并重命名为后一个文件,上面的python脚本命名为cp.py,进该目录执行该脚本
python在终端中打开或编辑操作
x=open('文件名') //打开想要编辑或查看的文件
x.writelines("xxxx\n") //\n代表回车
x.readline() //按行读取
x.seek(i) //调整光标到第行
x.flush() //保存
x.close() //退出,关闭打开的文件
>>>with open('文件名') as x: //用with打开文件可以防止中间忘记关闭,这种会自动保存并关闭
... x.readline()
...
Python基础(二):斐波那契数列、模拟cp操作、生成8位随机密码的更多相关文章
- python基础练习 斐波那契数列
转载于知乎刘奕聪的方法 一 f = [1, 1]print([f.append((f[-1] + f[-2])) or f.pop(0) for i in range(100)]) /// f.ap ...
- Python与Go斐波那契数列
#!/usr/bin/env python # -*- coding: utf-8 -*- # 斐波那契数列 def fibonacci_sequence(num): aa = 0 b = 1 li ...
- python练习:斐波那契数列的递归实现
python练习:斐波那契数列的递归实现 重难点:递归的是实现 def fib(n): if n==0 or n==1: return 1 else: return fib(n-1)+fib(n-2) ...
- 如何使用Python输出一个[斐波那契数列]
如何使用Python输出一个[斐波那契数列]Fibonacci 斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonac ...
- Python递归及斐波那契数列
递归函数 在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数.举个例子,我们来计算阶乘 n! = 1 * 2 * 3 * ... * n,用函数 fact(n)表示,可 ...
- Python 实现 动态规划 /斐波那契数列
1.斐波那契数列 斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数 ...
- Python递归函数与斐波那契数列
定义:在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数. 阶乘实例 n = int(input(">>:")) def f(n): s ...
- python练习题-打印斐波拉契数列前n项
打印斐波拉契数列前n项 #encoding=utf-8 def fibs(num): result =[0,1] for i in range(num-2): result. ...
- Python练习笔记——斐波那契数列
斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一 ...
- Python生成器实现斐波那契数列
比如,斐波那契数列:1,1,2,3,5,8,13,21,34.... 用列表生成式写不出来,但是我们可以用函数把它打印出来: def fib(number): n, a, b = 0, 0, 1 wh ...
随机推荐
- [CSP-S模拟测试]:antipalindrome(数学)
题目传送门(内部题58) 输入格式 第一行一个数$T$表示数据组数.接下来每行两个数$n$和$m$. 输出格式 $T$行,每行一个答案,对${10}^9+7$取模. 样例 样例输入: 25 66 5 ...
- [CSP-S模拟测试]:旅行(数学+线段树)
题目传送门(内部题12) 输入格式 第一行,一个整数$n$,代表树的点数.第二行,$n$个整数,第$i$个整数是$B_i$,描述排列$B$.接下来$n−1$行,每行两个整数$u,v$,描述一条树边$( ...
- spring boot 尚桂谷学习笔记08 Docker ---Web
------Docker------ 简介:Docker是一个开元的应用容器引擎,性能非常高 已经安装好的软件打包成一个镜像放到服务器中运行镜像 MySQL容器,Redis容器...... Docke ...
- ZwQueryDirectoryFile用法
1. 当返回值为STATUS_SUCCESS时,返回的字节数保存在IoStatusBlock.Information字段中: 2. 如果FileName字段被指定了,那么对于同时指定的FileHand ...
- [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent c ...
- Prim算法生成迷宫
初始化地图 function initMaze(r,c){ let row = new Array(2 * r + 1) for(let i = 0; i < row.length; i++){ ...
- P3375 【模板】KMP字符串匹配——kmp算法
先上一波题目 https://www.luogu.org/problem/P3375 kmp模板 看了好久才想起来是个什么东西qwq #include<cstdio> #include&l ...
- Android(一)Android Eclipse环境搭建
SDK Manager下载实在是太慢了,不知道什么时候能下完,所以我是通过手工下载的. Android SDK 手工下载各个包然后解压到Android对应的目录 API对应的是platforms目录 ...
- 任正非:5G技术只独家卖给美国!不卖给韩国、日本、欧洲
https://v.qq.com/x/page/g3001d0xvxe.html 我只转个标题,细节不管了. 呃,实际上就是说,老任头也决定向美国低头了,对不. 不过,也确实没办法. 该起床吃钙片了.
- SetViewportOrgEx和SetWindowOrgEx
在MM_TEXT映射模式下使用这两个函数. 对于 BOOL SetViewportOrgEx( HDC hdc, // 设备内容HANDLE int X, // 新Viewport的x坐标 int Y ...