安装依赖包
yum -y install gcc gcc-c++ zlib-devel openssl-devel readline-devel libffi-devel sqlite-devel tcl-devel tk-devel
wget https://www.python.org/ftp/python/3.8.13/Python-3.8.13.tgz
tar zxf Python-3.8.13.tgz
cd Python-3.8.13
./configure --prefix=/usr/local
make&&make install
安装 Pycharm
Pycharm 设置中文
Pycharm使用
加注释 : 选择行数 crtl +? 去掉注释:crtl+?
; 允许同一行但不推荐
例如;
分开写
a=3
b=4 推荐 这种写法
一行写(不推荐)
a=3;b=4 # 不推荐,可读性差
Python中 “字符串” 必须有引号,单双引号表示相同的含义,
如果不加引号,Python会把它当成一个名称,如果该名称没有定义将会报错
print('hello world') #语句各项之间默认用空格分隔
print('hello','world')
print('hello','world',sep='***') #语句各项之间也可以自定义分隔符
print('hello'+'world') #字符串可以使用+进行拼接
print('hello world',end='AAA') #print语句默认最后加入一个回车\n,可以用end来自定义结束
username = input('请输入用户名:')
print('欢迎登录',username)
print('欢迎登录'+ username)
-变量名全部采用小写字母
-简短、有意义
-多个单词间用下划线分隔
-变量名用名词,函数名用谓词(动词+名词)
-类名采用驼峰形式
n=n+1 或者n+=1 n*=1 #等价于n=n*1
赋值语句自右向左运算,首先取出n的值,再计算n+1的值得到11,最后11赋值给n
5/2 值为2.5
5//2 值为2 取整除 - 返回商的整数部分(向下取整)
5%2 值为1 求余,也被称作模运算,结果为1
2**3 值为8 2的3次方,乘方、幂运算
< <= > >= == != <>
10<20<30 支持连续比较
10<20>15 相当于10<20 and 20>15 不推荐10<20>15这样的写
and not or
and 两边为true
not 假变正
or 一个为正就为正
今天写到 print() input()
https://www.jianshu.com/ 搜索“ python百例 " 从下面开始做 1-5
print('hello world!')
if 3>0:
print("ok")
print("yes")
x = 4
y = 5
print("hello world!")
print("hello","world!") # 逗号自动添加默认的分隔符:空格
print("hello"+"world") # 加号表示字符拼接
print("hello","world",sep="***") #单词间用 *** 分隔
print("#" * 50) # *号表示重复50遍
print("how are you?",end="") # 默认print会打印回车,end=“ ” 表示不要回车
number = input("请输入数字: ") # input用于获取键盘输入
print(number)
print(type(number)) # input获得的数据是字符型
print(number + 10) # 报错,不能把字符和数字做运算
print(int(number) + 10) # int可将字符串10转换成数字10
print(number + str(10)) # str将10转换为字符串后实现字符串拼接
################################################################################################
(1)int整数(有符号整数,没有小数点)
(2)bool布尔值 :Ture/false Ture=1 , false=0
(3)float浮点数:有小数点
(4)complex复数:共轭复数
对于整数,没有任何前缀Python默认识别为10进制数
以0o开头表示8进制,0b开头表示2进制 , 以0x开头表示16进制
在引号中一系列字符,单双引号没有区别
三引号:三个连续的单引号或者双引号。它能够保存输入的格式,允许多行输入
下标和切片操作
第一个字符索引是0 ,最后一个字符的索引是-1
索引下标运算符[ ] 切片运算符[:] [::2] 表示步长值
py_str="Python"
len(py_str) #查询长度
print("len(py_str)") #打印py_str变量的长度
py_str[0] #下标从0开始"Python"[0] 意义一样
print(py_str[0]) #可以截取字符串第一个字符
py_str[6] #索引超出范围,报错
py_str[len(py_str) -1] #字符串总长度减一,得到最后一个字符的下标
py_str[-1] #也可以得到最后一个下标
py_str[2:4] #表示下标包含,结束下标不包含
py_str[2:6] 得到 ‘thon’
py_str[2:600] #下标超出范围,切片不报错 ‘thon’
py_str[2:] #结束下标不写,表示取到结尾
py_str[0:2] 得到‘py’
py_str[:2] 得到 ‘py’ #开始下标不写,表示从开头开始
py_str[2:5] 得到 "tho" #从2开始到5结束 5-2=3
py_str[::2] 得到 "pto" #表示步长值是2
py_str[1::2] 得到 "yhn" #从1开始步长值是2
py_str[::-1] 得到 "nohtyp" #表示从右向左取步长值为-1
py_str + " is cool" #+号表示简单拼接
print(py_str + " is cool" ) 得到 Python is cool
"*" * 50 # *号重复50次
print("*" * 50) 得到 **********************************
print(py_str * 3) 得到 PythonPythonPython
"t" in py_str
print("t" in py_str ) 得到 True
"to" in py_str
print("to" in py_str ) 得到 False
print("to" not in py_str ) 得到 True
可以将列表当成普通的“数组" ,它能保存任意数量,任意类型的Python对象
列表: 它是一个容器,可以存放各种数据
列表
alist = [10 ,20 ,"li" ,"da",[1,2]]
print(len(alist)) 得到5
alist[2:4]
print(alist[2:4]) 得到 ["li","da"]
alist[-1] =100 #列表项可以重新赋值
print(alist) 得到[10,20,"li","da","100"]
alist.append(200) #向列表尾部增加一项
print(alist) 得到 [10,20,"li","da","100","200"]
相当于是静态的列表,它的项目不可变
atuple =(10,20,"li","da")
atuple[-1]
print(atuple[-1]) 得到 da
atuple[0] =100 #报错,元组不能修改
采用key:val 对存储的数据类型,key不能重复
adict={"name":"大锤","age":18}
adict["name"] # 通过key取出value
print(adict["name"]) 得到 大锤
18 in adict 得到 Flase
"age" in adict 得到True
adict["sex"]="female" #key不在字典中则增加一项
print(adict) 得到{"name":"大锤","age":18,"sex":"female"}
adict["age"]=20 # age已是字典的key,修改age的值
print(adict) 得到{"name":"大锤","age":20,"sex":"female"}
—————————————————————————————
按数据类型比较 -----------------------重要、必须背下来
按存储模型分类
-标量类型 : 数值、字符串 标量:只有一种类型,不能存储其他类型。数字、字符串
-容器类型:列表、元组、字典 容器:能包含各种数据。列表、元组、字典
按更新模型分类
-可变类型:列表、字典
-不可变类型:数字、字符串、元组
按访问模型分类
-直接访问:数字
-顺序访问: 字符串、列表、元组
-映射访问:字典
例如:
alist = [10 ,20 ,"li" ,"da",[1,2]]
blist = alist
blist.append(30)
print(alist) 得到[10 ,20 ,"li" ,"da",[1,2],30]
print(blist) 得到 [10 ,20 ,"li" ,"da",[1,2],30] 变得一样所以写程序容易出现bug
blist=alist.copy()
blist.append(30)
print(alist) 得到[10 ,20 ,"li" ,"da",[1,2]]
print(blist) 得到 [10 ,20 ,"li" ,"da",[1,2],30]
words = "tom\njeff\njay\nmikes"
if "tom" in words :
print("yes")
if "tom" not in words :
print("not in")
else:
print("tom in words")
if -0.0 :
print("0k") #任何值为0的数字都是False,非0为True //这里不打印
if -0.01 :
print("-0.01 is ok") #这里可以打印True
if ' ' :
print("space is true") #任何非空对象都是True ,空位False ,打印
if '' :
print("空字符串是False") #False不打印
if None:
print("None也是False,表示空") #False不打印
判断合法用户
###############################################################################################
判断合法用户
import getpass #导入名为getpass 的模块
username = input("username:")
password = getpass.getpass("password:")
if username == "bob" and password == "123456" :
print("Login successful")
else:
print("Login inorrect")
import random
number = random.randint(1,100) #生成1-100间的随机数字,包含1和100
print("number ->",number)
answer = int (input("猜数1-100:")) #将用户输入的字符数字转成真正的int数字
if answer > number:
print("猜大了")
elif answer< number:
print("猜小了")
else:
print("猜对了")
import random
number = random.randint(1,100)
while True:
answer = int(input("\033[34;1m猜数1-100:\033[0m"))
if answer > number :
print("\033[34;1m猜大了\033[0m")
elif answer <number:
print("\033[34;1m猜小了\033[0m")
else:
print("\033[31;1m猜对了[\033[0m")
break
import random
all_choise = ['石头', "箭头", "布"]
win_list = [['石头', '剪刀'], ['布', '石头'], ['剪刀', '布']]
prompt = """1.石头
2.剪刀
3.布
请出拳(0/1/2):"""
computer = random.choice(all_choise)
index = int(input(prompt))
player = all_choise[index]
print("你的出拳:", player, "计算机出拳:", computer)
if player == computer:
print("\033[32;1m平局\033[0m")
elif [player, computer] in win_list:
print("\033[35;1m你赢了\033[0m")
else:
print("\033[31;1m你输了\033[0m")
import random
tries = 0 #设置计数器,用户最多猜3次
number = random.randint(1,10)
while tries<3:
answer = int(input("猜数(1-10):"))
if answer > number:
print("猜大了")
elif answer < number:
print("猜小了")
else:
print("猜对了")
break
tries +=1
else:
print("数字是:",number)
————————————————————————————————————---------------
例如:
a = 100
b = 80
if a<b:
smaller = a
else:
smaller =b
以上 写法,可简写为
smaller = a if a<b else b
score = int(input("请输入你的成绩:"))
if 70>score>=60:
print("及格")
elif 80>score>=70:
print("良")
elif 90>score>=80:
print("好")
elif score>=90:
print("优秀")
else:
print("你要努力了")
##################################################################################################
for i in :
range(10) 生成列表[0,1,2,3,4,5,6,7,8,9,]
range(6,10) 生成[6,7,8,9,]
例如:
range(5)
print(list(range(5))) //用list函数 把range(5) 转换成列表
得到 [0, 1, 2, 3, 4]
for i in range(3): #[0,1,2] 外侧循环控制打印哪一行
for j in range(i+1): #[0] [0,1] [0,1,2] 内层循环控制行内打印几次
print("hello",end=" ") #多个hello打印到同一行
print(j)
print() #每一行结尾需要打印回车,否则就成为一行
"%sX%s=%s" %(1,2,2) #得到 1X2=2 注释符里面不可以加变量可以加 字符串输出%s占位
打印9*9 乘法表
for i in range(1,10):
for j in range(1,i+1):
print("%sx%s=%s" %(j,i,i*j),end="\t")
print()
列表解析:快速生成列表
[10] #得到[10]
[10+5] #得到[15]
[10+5 for i in range(1,11)] #得到 [15, 15, 15, 15, 15, 15, 15, 15, 15, 15]
[10+i for i in range(1,11)] #得到 [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
[10+i for i in range(1,11) if i % 2 == 1] #得到 [11, 13, 15, 17, 19]
["192.168.1."+str(i) for i in range(1,5)] #得到 ['192.168.1.1', '192.168.1.2', '192.168.1.3', '192.168.1.4']
open及file file Python2才有,Python3已经不用了,用open
open read readline readlines close
cp /etc/hosts /tmp/hosts
#打开文件,没有指定打开方式,默认以r 读的方式打开,以r打开,不能写。文件不存在则报错
python3
f = open(“/tmp/hosts”) #默认加r打开了
data = f.read() # read 默认将全部内容读入内存
f.close() #关闭文件
print(data)
data #可以查看到原始数据,也就是\n 没有被转换成换行。
f = open("/tmp/hosts")
f.read(10) #读取10个字节
f.read(10) #继续向后读10个字节
f.readline() #读一行
f.readlines() #所有的行读出来放到列表中,每一行是列表的一项
f.close()
练习:
f = open("/bin/ls","rb") #打开文本文件,必须明确指定是b(bytes) 二进制文件要加b,要不会报错
f.wirte("jsdf") #报错 ,以r打开不能写入只能读
f.read(10)
f.close()
f = open("/tmp/zhuji","w") #以w打开文件,文件不存在则创建,存在则清空 (慎用)
f = open("/tmp/zhuji","wb") #清空或者创建可以写入图片
f.write("hello world!\n") #写入13个字节
f.flush() #立即将数据写入硬盘,否则将会暂存在缓冲区
f.wirtelines(["2nd line.\n","3rd line.\n"])
f.wirte(100) #报错,只能将字符写到文件,不能是其他数据
f.close()
f =open("/tmp/zhuji","a") #a是追加方式打开(为了打开可以写入不清空)
f.wirte("new line.\n")
f = open("/tmp/zhuji","r+") #以读写方式打开
f.write("abcde") #abcde 将会在开头把原文件覆盖
f.tell() #获取文件指针的位置
f.read(8) #从文件指针开始的位置向后读8个字符
f.seek(3,0) #将文件指针称动到开头偏移3个字节
f.read(2) #读文件第4、5 个字符
f.seek(0,2) #移动指针到文件结尾
f.write("my test.\n")
f.flush()
f.read() #因为已经到文件结尾,所有读到的是空串
f.seek(0,0) #移动指针到文件开头
f.readline()
#读第一行的内容
###########################################################################################
文件操作可以使用with语句,with语句结束时,文件自动关闭
whit open("/tmp/zhuji") as f: #相当于 f = open("/tmp/zhuji")
... line = f.readline()
line #文件第一行
f.readline()
#出错,因为文件已经关闭
逐行处理文本文件,更常用的方法是for循环
>>> with open("/tmp/zhuji") as f:
... for line in f:
... print(line,end=" ")
参考代码:
src_fname = "/bin/ls"
dst_fname = "/tmp/list"
src_fobj = open(src_fname,"rb")
dst_fobj = open(dst_fname,"wb")
while True:
data = src_fobj.read(4096)
if not data: #读不到数据,意味着已经读完了
break
dst_fobj.write(data) #读到数据,则写入目标文件
src_fobj.close()
dst_fobj.close()
或者
src_fname = "/bin/ls"
dst_fname = "/tmp/list"
with open(src_fname,"rb") as src_fobj:
with open(dst_fname,"wb") as dst_fobj:
while True:
data = src_fobj.read(4096)
if not data:
break
dst_fobj.write(data)
#################################################################################################
函数是用def 语句来创建的,语法如下:
def function_name(arguments):
"function_documentation_string"
function_body_suite
例如:
def generate_fib():
fib = [0,1]
for i in range(8):
fib.append(fib[-1]+fib[-2])
return fib
generate_fib() #调用函数,即将函数内的代码运行一遍
alist = generate_fib()
print(alist)
blist = [i*2 for i in alist]
print(blist)
def generate_fib(n):
fib = [0,1]
for i in range(n-2):
fib.append(fib[-1]+fib[-2])
return fib
a = generate_fib(10)
print(a)
b = generate_fib(20)
print(b)
x = int(input("length:"))
c = generate_fib(x)
print(c)
——————————————————————————————————————
import sys
print(sys.argv) #sys.argv是模块中名为argv的列表,用于存储位置参数
写一个cp命令 在Linux运行
import sys
def copy(src_fname,dst_fname):
with open(src_fname,"rb") as src_fobj:
with open(dst_fname,"wb") as dst_fobj:
while True:
data = src_fobj.read(4096)
if not data:
break
dst_fobj.write(data)
copy(sys.argv[1],sys.argv[2])
def pstar(n=30)
print("*"*n)
pstar() #调用函数默认为打印30
pstar(50) #打印50
—————————————————————————————————————————
模块就是一个.py的文件,把文件名的.py移除掉就是模块名
比如:一个文件夹有两个文件star.py 和test.py
star.py中:
hi = "hello world!"
def pstar(n=30):
print("*"*n)
test.py 中:
import star
print(star.hi)
star.pstar(10)
在cp.py 中使用import star 就是使用star模块
创建randpass.py 脚本,要求如下:
参考代码:
import random
import string
all_chs = string.ascii_letters+string.digits
def randpass(n=8):
result =""
for i in range(n):
ch = random.choice(all_chs)
result+=ch
return result
if __name__ == '__main__':
a = randpass()
print(a)
print(randpass(4))
################################################################################################
import shutil
f1 = open("/etc/hosts")
f2 = open("/tmp/zj.txt")
shutil.copyfileobj(f1,f2) #copy 文件对象
f1.close
f2.close
shutil.copyfile("/etc/hosts","/tmp/abcd.txt") #copy文件名
shutil.copy("/etc/hosts","/tmp/aaa.txt") #目标可能是目录
shutil.copy("/etc/passwd","/tmp/")
shutil.copy2("/etc/passwd","/tmp/") #相当于cp -p 拷贝权限
shutil.copytree("/etc/security","/tmp/anquan") # cp -r
shutil.move("/tmp/zj.txt","/var/tmp/") #相当于mv
shutil.rmtree("/tmp/anquan") #相当于rm -rf ,但只能删除目录不能删除单独文件
shutil.rmtree("/var/tmp/zj.txt") # 不能删除单个文件
import os
os.remove("/var/tmp/zj.txt") #这个可以删除单个文件
shutil.chown("/tmp/passwd",user="bob",group="bob") #相当于chown
使用help可以查看更多
例: help(shutil.rmtree)
Python支持链式多重赋值
x = y = 10
id(x)
9348224 #显示变量在内存的地址
id(y)
9348224
x = 20 #修改x = 20 x变了,y不变
y = 10 #y的值不变,数值是不可变的
a = b = [10,20]
a[0] = 100
a
[100,20]
b
[100,20] #列表是可变的
a,b = 10,20 #相当于 a = 10;b = 20
a,b = b,a #a和b的值互换
——————————————————————————————————————————
——————————————————————————————————————————
['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue',
'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is',
'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
import keyword
print(keyword.kwlist)
keyword.iskeyword("len") #判断len是否是关键字 或 "len" in keyword.kwlist 等等
——------------------------------------------------------------------------------------------
http://yiyibooks.cn/ -> python352文档 - > 库参考
编写程序时,应该建立一种统一且容易阅读的结构,并将它应用到每一个文件中去
#!/usr/bin/env python #起始行
"this is a test module" #模块文档字符串
import sys #导入模块
import os
debug = Ture #全局变量声明
class FooClass(object): #类定义
"Foo class"
pass
def test(): #函数定义
"test function"
foo = FooClass()
if_name_ == '_main_': #程序主体
test()
import os
def get_fname():
while True:
fname = input("filename:")
if not os.path.exists(fname): #判断文件是否存在
break
print("文件已存在,请重试")
return fname
def get_content():
content = []
while True:
line = input('("end" to quit)>')
if line == "end":
break
content.append(line)
return content
def wfile(fname,content):
with open(fname,"w") as fobj:
fobj.writelines(content)
if __name__ == '__main__':
fname = get_fname()
content = get_content()
content = [line +"\n" for line in content] #为每行加上回车
wfile(fname,content)
#############################################################################################
seq[ind] 获取下标为ind的元素 a = [“h”,“e”,“l”,“l”,“o”] a[3] = l
seq[ind1:ind2] 获取下标从ind1到ind2间的元素集合 a = [“h”,“e”,“l”,“l”,“o”] a[2:4] = [“l”,“l”]
seq*expr 序列重复expr次 print(“#”*5) 得到 #####
seq1+seq2 连接序列seq1和seq2 拼接(同类型) “abc”+“123” 或者
例:
“abc” +[10,20] 不可以不同类型 修改为 [“abc”] +[10,20]
obj in seq 判断obj元素是否包含在seq中
obj not in seq 判断obj元素是否不包含在seq中
函数 | 意义 |
---|---|
list(iter) | 把可迭代对象转换为列表 |
str(obj) | 把obj对象转换成字符串 |
tuple(iter) | 把一个可迭代对象转换成一个元组对象 |
len(seq) | 返回seq的长度 |
max(iter,key=None) | 返回iter中的最大值 |
enumerate | (枚举) 接受一个可迭代对象作为参数,返回一个enumerate对象 返回是元组 |
reversed(seq) | (翻转) 接受一个序列作为参数,返回一个以逆序访问的迭代器 |
sorted(iter) | (排序) 接受一个可迭代对象作为参数,返回一个有序的列表 |
------------------------------------------
list(10) #无法装列表。数字无法转
list("hello") #列表
#结果得到 ["h","e","l","l","o"]
list(("hello","world"))
["hello","world"]
str(obj) #字符串
str(10)
"10"
tuple(iter) #元组
tuple(abc)
("a","b","c")
a = "hello"
len(a) 得到5
names = ["bob","alice","tom"]
max(name) 得到tom 按第一个字母排序
min(names) 得到alice
hi = "hello"
alist = [10,20,30]
for ind in range(len(hi)):
print(ind,hi[ind])
for item in enumerate(alist):
print(item)
for ind,val in enumerate(alist):
print(ind,val)
print(list(reversed(alist))) #翻转
for i in reversed(alist)
print(i)
print(sorted(alist)) #排序
比较操作符:字符串大小按 ASCII码值大小进行比较
切片操作符:[]、[:] 、[::]
成员关系操作:in 、not in
———————————————————————————————————————————
import keyword
import string
first_chs = string.ascii_letters+"_"
other_chs = first_chs+string.digits
def check_id(idt):
if keyword.iskeyword(idt):
return "%s是关键字" %idt
if idt[0] not in first_chs:
return "首字符不合法"
for ind,ch in enumerate(idt[1:]):
if ch not in other_chs:
return "第%s个字符不合法" %(ind+2)
return "%s是合法的标识符" %idt
if __name__ == '__main__':
idt = input("请输入字符串:")
print(check_id(idt))
%c
%s #优先用str()函数进行字符串转换
%d /%i #转成有符号十进制数
%#o #转成无符号八进制数
%#x #转成无符号十六进制数
%e /%E #转成科学计数法
%f /%F #转成浮点数
%10s%10s #填充格式
%-10s%-10s #左对齐
"" %()
print("%s" % a)
"%s: %s" % ("bob",22) #%s / %d 常用
"%s: %d" % ("bob",22)
"97 is %c" % 97 # %c转换数字成为对应的ASCII码,
"97 is %#o" % 97 #不常用
"97 is %#x" % 97 #不常用
"10000 is %e " %10000 #不常用
"10/3 is %f" %(10/3) #不常用
"%10s%10s" % ("name","age") #常用,定义字段宽度为10个字节
"%-10s%-10s" % ("name","age") #常用,左对齐
(功能和上面%字符串格式化一样)
使用位置参数
- "my name is{},age{}" .format("hoho",18)
使用关键字参数
- "my name is {name},age is {age}".format({"name":"bob","age":23})
填充与格式化
-{:[填充字符][对齐方式<^>][宽度]}
使用索引
- "name is {0[0]} age is {0[1]}" .format(["bob",23])
"{}: {}" .format("bob",22)
"bob: 22"
"{1}: {0}" .format("bob",22)
"bob: 22"
"{0[1]}: {0[0]}" .format([22,"bob"])
参考代码:
import sys
import subprocess
#import randpass
import random
import string
all_chs = string.ascii_letters+string.digits
def adduser(username,password,fname):
info = """用户信息:
用户名:%s
密码:%s
""" %(username,password)
subprocess.call("useradd %s" % username,shell=True)
subprocess.call(
"echo %s |passwd --stdin %s" %(password,username),shell=True
)
with open(fname,"a") as fobj:
fobj.write(info)
def randpass(n=8): #创建随机8位密码
result=""
for i in range(n):
ch=random.choice(all_chs)
result+=ch
return result
if __name__ == '__main__':
password = randpass()
fname = "/tmp/mima.txt"
adduser(sys.argv[1],password,fname)
.原始字符串操作符是为了对付那些在字符串中出现的特殊字符
.在原始字符串里,所有的字符都是直接按照字面的意思来使用,没有转义特殊或不能打印的字符
例:
winPath = "c:\windows\new\temp"
print(winPath) # \t 成为tab \n成为回车
c:\windows
ew emp
newPath = r"c:\windows\temp" # r表示真实字符串`原始字符串
print(newPath)
c:\windows\temp
newPath #看到Python是如何存储的 其实 r 是加多\
c:\\windows\\temp
——————————————————————————————————————
string.capitalize(): # 把字符串的第一个字符大写
string.center(width) #返回一个原子符串居中,并使用空格填充至长度width 的新字符串
string.count(str,beg=0,end=len(string)) #返回str在string里面出现的次数,如果beg或者end指定则返回指定范围内str出现的次数
string.upper() #字符串变大写
string.strip() #删除两端空白字符,
string.lstrip() #删除左边空白字符
string.rstrip() #删除右边空白字符
string.lower() #字符串变小写
string.startswith("he") #是以he开头吗
string.endswith("abc") #是以abc结尾吗
string.replace("l","m") # l 替换为m
string.ljust(50,"*") # 宽度为50,左边对齐,空格补充为*
string.rjust(50,"*") #宽度为50,右边对齐,空格补充为*
string.isdigit() #判断字符串是不是全部数字
string.islower() #判断是否全部小写
string.isupper()
string.isidentifier() #判断是否符合合法标识符
" hello world ".strip() #删除两端空白字符
hi = "hello world"
hi.upper() #字符串变大写
hi.lower() #字符串变小写
hi.startswith("h") #以h开头吗?
hi.startswith("he")
hi.endswith("abc") #以abc结尾吗?
hi.replace("l","m") #替换
hi.center(50) #居中
hi.center(50,"*")
hi.ljust(50,"*")
hi.rjust(50,"*")
"1234".isdigit() #判断是否是数字
True
"hao123".isdigit()
False
"hao123".islower() #是否小写
————————————————————————————————————————————
·列表是有序、可变的数据类型
·列表中可以包含不同类型的对象
·列表可以由 [ ] 或工厂函数创建
·支持下标及切片操作
列表方法 | 操作 |
---|---|
list.append(obj) | 向列表中添加一个对象 |
list.count(obj) | 返回一个对象obj在列表中出现的次数 |
list.extend(seq) | 把序号seq的内容添加到列表中 |
list.index(obj) | 返回obj对象的下标 |
list.insert(index,obj) | 在索引量为index的位置插入对象obj |
list.reverse() | 原地翻转列表 |
alist = [10,20,30,"bob","alice"]
alist.remove("bob") #删除第一个bob
alist.append("25") #添加一个对象
alist.sort() #排序升序
alist.reverse() #翻转
alist.pop() #默认删除最后一项
alist.pop(1) #弹出
alist.insert(1,50) #在下标为1的位置插入50
alist.extend([200,10,39]) #扩展列表
alist.extend("abc") #会把abc 分开加到列表
alist.append("abc") #注意和extend的区别
alist.index(50) #获取50的下标,没有50这个元素则报错
————————————————————————————————————————
atuple = (10,20,30,[1,2,3])
atuple.count(20) #统计有多少个20
atuple.index(20) #第一个20的下标
atuple[-1].append(4) #理解即可,很少有应用
a= (10)
len(a) #报错
type(a) #整数
a =(10,) #元组必须有逗号
len (a)
1
type(a)
参考代码:
stack = [] #全局变量从定义开始一直到程序结束,任何地方都可见、可用
def push_it():
item = input("数据").strip()
if item:
stack.append(item)
def pop_it():
if stack:
print("从栈中弹出了%s" % stack.pop())
else:
print("\033[32;1m空栈\033[0m")
def view_it():
print("\033[31;1m%s\033[0m" % stack)
def show_menu():
cmds = {"0": push_it,"1":pop_it,"2":view_it}
prompt = """(0)压栈
(1)出栈
(2)查询
(3)退出
请选择(0/1/2/3)"""
while True:
choice = input(prompt).strip()[0]
if choice not in "0123":
print("无效输入,请重试")
continue
if choice == "3":
print("Bye-bye")
break
cmds[choice]()
if __name__ == '__main__':
show_menu()
##############################################################################################
adict = {"name":"bob","age"20}
dict = (["ab","cd",("name","niu")])
{}.fromkeys(["niu","wang","li"],"male")
20 in adict
False
"age" in adict
True
查询代码
for key in adict:
print("%s:%s" % (key,adict[key)]))
print("%(name)s is %(age)s years old" %adict)
通过key更新字典,如果key不在字典中则增加新增,在字典中则修改**
adict["email"] = "[email protected]"
print(adict)
{'name': 'bob', 'age': 20, 'email': '[email protected]'}
adict["age"] = 22
print(adict)
{'name': 'bob', 'age': 22, 'email': '[email protected]'}
adict.keys() #查询key的值或 直接adict
for key in adict.keys():
print(key)
或者
for key in adit:
print(key)
list(adict.values())
for key,val in adict.items():
print("%s: %s" % (key ,val) )
dict.copy()
dict.get(key,default = none)
dict.items()
adict[phone] #没有会报错
adict.get("phone") #没有指定则none 获取key为phone的值 ,重点
adict.get("phone","110") #获取key为phone的值,没有返回110
adict.popitem() #随机弹出一项
adict.pop("email") #弹出key是email的项
adict.update({"aaa":100,"bbb":200})
print(adict.get("phone") ) #获取获取key为phone的值
要把Unix 文档换行转为windows文本换行,>>>> 使用命令Unix2dos 文件名
要把windows 文档换行转为Unix文本换行,>>>> 使用命令dos2Unix 文件名
————————————————————————————————————————
import time
import sys
n = 0
print("#"*19,end="")
b = "\033[32;1m@\033[0m"
while True:
print("\r%s%s%s" % ("#"*n,b,"#"*(19-n)),end="") # \r 回车不换行
sys.stdout.flush() # 立即在屏幕上输出,不要放到缓冲区
n+= 1
time.sleep(0.3)
if n == 20:
n = 0
——————————————————————————————————————————
集合 :由不同元素组成的set,元素只能是不可变对象。相当于是无值的字典
集合类型操作符
集合支持用in 和not in 操作符检查成员
能够通过len() 检查集合大小
能够使用for 迭代集合成员
不能去切片,没有键
len(aset)
4
for ch in aset:
print(ch)
打印结果:
l
e
o
h
** | 联合,取并集
& 交集
bset = set("how")
aset = set("hello")
aset
{"h","o","l","o"}
bset
{"h","w","o"}
aset | bset #并集
{"w","e","h","
aset+bset # 报错
aset & bset #交集
{"h","0"}
aset - bset #差补,aset中有,bset中没有的元素
set.add() 添加成员
set.update() 批量添加成员
set.remove() 移除成员
实操:
aset = set("hello")
aset.add("new")
aset
{"h","o","l","e","new"}
aset.update("new")
aset
{"h","o","l","e","new","n"}
aset.update(["hello","world"])
aset
{"h","o","l","e","new","n","hello","wolrd"}
aset.remove("n")
aset
{"h","o","l","e","new","hello","wolrd"}
cset = set("ho")
cset.issubset(aset) #cset 是aset的子集吗
aset.issuperset(cset) # aset 是cset的超集吗
aset.intersection(bset) #aset & bset 交集
aset.union(bset) #aset | bset 并集
aset.difference(bset) #aset - bset 补差
cp /etc/passwd /tmp/
cp /etc/passwd /tmp/mima
修改mima,使之与passwd不完全一样
with open("/tmp/mima") as f:
aset = set(f)
with open("/tmp/passwd") as f:
bset = set(f)
with open("/tmp/result.txt","w") as f:
f.wirtelines(aset - bset)
导入方式:
import time
常用方法:
time.time() # 返回时间戳 ,自1970-1-1 0:00:00 到执行命令期间的秒数 (常用)
time.ctime() #当前日期、时间 (常用)
time.localtime() #返回九元组格式时间
time.sleep(3) #睡眠3秒 (常用)
time.strftime(“%Y-%m-%d %H:%M:%S”)
导入方式:
import datetime
实操:
from datetime import datetime ,timedelta
t1 = datetime.now() #把当前时间转换成时间对象
t1.year
t1.month
t1.day
t1.hour
t1.minute
t1.second
t1.microsecond
t2 = datetime(2018,10,10)
#转换字符串为datetime对象
t1 = datetime.strptime("Dec 12 2018","%b %d %Y")
t = datetime(2018,12,10)
t1>t
t = datetime.now()
days = timedelta(days = 100)
t1 = t -days
t2 = t +days
当程序运行时,因为遇到未解的错误而导致中止运行,便会出现traceback消息,打印异常
异常 | 描述 |
---|---|
NameError | 未声明/初始化对象 |
IndexError | 序列中没有没有此索引 |
SyntaxError | 语法错误 |
KeyboardInterrupt | 用户中断执行 |
EOFError | 没有内建输入,到达EOF标记 |
IOError | 输入/输出操作失败 |
参考代码:
try:
num=int(input("number:")) #把有可能发生异常的语句放到try中
result=100/num
print(result)
except (ValueError,ZeroDivisionError): #捕获异常
print("无效输入,必须输入非0数字")
except (KeyboardInterrupt,EOFError):
print("\nBye-bye")
else:
print(result) #异常不发生才执行的语句,放到else中
finally:
print("DONE") #不管是否发生异常都要执行的语句,放到finally中
这两种组合用的比较多
def set_age(name,age):
if not 0<age<150:
raise ValueError("年龄超过范围了(1-150)")
print("%s现在是%s岁了" %(name,age))
def set_age2(name,age):
assert 0<age<150,"年龄超过范围了(1-150)"
print("%s现在是%s岁了" %(name,age))
if __name__ == '__main__':
set_age("大牛",22)
set_age2("神通",255)
#############################################################################################
对文件系统的访问大多通过Python 的os模块实现
该模块是Python访问 —> 操作系统功能的主要接口
有些方法:
如copy等,并没有提供,可以使用shutil模块作为补充
函数 | 作用 |
---|---|
os.symlink() | 创建符号链接(软连接) |
os.listdir() | 列出指定目录的文件 |
os.getcwd() | 返回当前工作目录 |
os.mkdir() | 创建目录 |
os.chmod() | 改变权限模式 |
os.getatime() | 返回最近访问时间 |
os.chdir() | 改变工作目录 |
os.remove | 删除文件(只能删除文件和空目录) |
os.rmdir | 删除空目录 |
os.rmtree | |
os.rename | 重命名 |
参考代码:
**import os**
**相当于Linux命令**
os.getcwd() #pwd
os.mkdir("/tmp/demo") #mkdir /tmp/demo
os.chdir("/tmp/demo") #cd /tmp/demo
os.listdir() # ls
os.listdir("/home") #ls /home
os.mknod("mytest.txt") # touch mytest.txt
os.symlink("/etc/hosts","zhuji") #ln -s /etc/hosts zhuji
os.unlink("zhuji") #删除软连接
os.chmod("mytest.txt") #touch mytest.txt
os.rename("mytest.txt","test.doc") #mv mytest.txt test.doc
os.remove("zhuji") # rm -f zhuji
os.rmdir("/tmp/devops") #删除空目录
os.path.basename("/etc/sysconfig/network") #从/etc/sysconfig 切割network
os.path.dirname("/etc/sysconfig/network") #目录名称
os.path.join("/etc/sysconfig","network")
os.path.isfile("/etc/hosts") #是一个文件吗
os.path.isdir("/etc/hosts") #是一个目录吗
os.path.exists("/etc/hosts") #是否存在
os.path.islink("/etc/hosts") #是链接吗
普通的文件只能把字符类型数据写入到文件中,pickle可以把任意类型的数据存储到文件中,
将来还能无损地取出。
f = open("/tmp/mydata","w")
f.write("hello world!\n")
f.write(100) #不允许写入数字
f.write({"name:"bob"}) #不允许写入字典
f.close()
import pickle as p #导入模块时,为其取别名p
f = open("/tmp/data","wb")
adict = {"name":"bob","age":23}
p.dump(adict,f) #将字典存入文件
f.close()
import pickle as p
f = open("/tmp/data","rb")
mydict = p.load(f) #加载赋值
f.close()
################################################################################################
参考代码:
import os
import pickle
import time
def cost(record):
amount = int(input('金额:'))
comment = input('备注:')
date = time.strftime('%Y-%m-%d')
with open(record, 'rb') as fobj:
data = pickle.load(fobj)
balance = data[-1][-2] - amount
data.append([date, 0, amount, balance, comment])
with open(record, 'wb') as fobj:
pickle.dump(data, fobj)
def save(record):
amount = int(input('金额:'))
comment = input('备注:')
date = time.strftime('%Y-%m-%d')
with open(record, 'rb') as fobj:
data = pickle.load(fobj)
balance = data[-1][-2] + amount
data.append([date, amount, 0, balance, comment])
with open(record, 'wb') as fobj:
pickle.dump(data, fobj)
def query(record):
print('%-12s%-10s%-10s%-10s%-20s' % ('date', 'save', 'cost', 'balance', 'comment'))
with open(record, 'rb') as fobj:
data = pickle.load(fobj)
for item in data:
print('%-12s%-10s%-10s%-10s%-20s' % tuple(item))
def show_menu():
record = r'D:\a\record.data'
if not os.path.exists(record):
init_data = [
[time.strftime('%Y-%m-%d'), 0, 0, 10000, '开始记账'],
]
with open(record, 'wb') as fobj:
pickle.dump(init_data, fobj)
cmds = {'0': cost, '1': save, '2': query}
prompt = """(0) 记录开销
(1) 记录收入
(2) 查询收支
(3) 退出
请选择(0/1/2/3): """
while True:
try:
choice = input(prompt).strip()[0]
except IndexError:
continue
except (KeyboardInterrupt, EOFError):
choice = '3'
if choice not in '0/1/2/3':
print('无效输入,请重试')
continue
if choice == '3':
print('\nBye-bye')
break
cmds[choice](record)
if __name__ == '__main__':
show_menu()
def foo():
print("in foo")
boo() #可以先使用再定义
def boo():
print("in boo")
foo()
foo #function foo at 0x7f18ce311b18
def get_age(name,age):
print("%s is %s years old." % (name,age))
使用一对圆括号() 调用函数,如果没有圆括号,只是对函数的引用
任何输入的参数都必须放置在括号中
操作:
get_age() #error 没有加参数
get_age(“bob”,25,26) #error
get_age(“bob”,25) #正确
get_age(25,“bob”) #语法没有错误,语义不对
get_age(age = 25,name = “bob”) #正确
get_age(age = 25, “bob”) #语法错误,key = val 形式必须在后
get_age(25,name = “bob”) #错误,name得到多个值
get_age(“bob”,age = 25) #正确
Python允许程序员执行一个没有显式定义参数的函数
相应的方法是通过一个把元组(非关键字参数)或字典(关键字参数)作为参数数组传递给函数
def myfunc(*args): # *标识args 是个元组
print(args)
def myfunc2(**kwargs): # **标识kwargs 是字典
print(kwargs)
if __name__ == '__main__':
myfunc() #得到 ()
myfunc(10) #得到 (10,)
myfunc(10,20,30) # 得到 (10, 20, 30)
myfunc(10,20,30,"bob","tom") #得到 (10, 20, 30, 'bob', 'tom')
myfunc2(name="bob") #得到 {'name': 'bob'}
myfunc2(name="bob",age="23") #得到 {'name': 'bob', 'age': '23'}
def add(x,y):
print(x+y)
if __name__ == '__main__':
alist = [10,20]
add(*alist) #调用函数时,参数加上 * 表示将序列对象拆开
add(*"ab") #将字符串拆开
import random
def add(x,y):
return x +y
def sub(x,y):
return x - y
def exam():
cmds = {"+":add,"-":sub}
#cmds = {"+":lambda x,y:x+y,"-":lambda x,y:x-y} #使用这个lambda可以忽略两个函数add和sub
nums = [random.randint(1,100) for i in range(2)]
nums.sort(reverse=True) #降序排列
op = random.choice("+-")
prompt = "%s%s%s=" % (nums[0],op,nums[1])
# if op == "+":
# result = nums[0] + nums[1]
# else:
# result = nums[0] - nums[1]
result = cmds[op](*nums)
tries = 0
while tries <3:
try:
answer=int(input(prompt))
except (ValueError,UnboundLocalError):
print("请输入数字")
continue
if answer == result:
print("very good")
break
else:
print("答错了")
tries +=1
else:
print("%s%s" %(prompt,result))
if __name__ == '__main__':
while True:
exam()
try:
yn=input("continue(y/n|Y/N)").strip()[0]
except IndexError:
continue
except (KeyboardInterrupt,EOFError):
yn="n"
if yn in "Nn":
print("Bye-bye")
brea
Python额允许用lambda 关键字创造匿名函数
匿名是因为不需要以标准的def 方式来声明
一个完整的lambda “语句” 代表了一个表达式,这个
表达式的定义体 必须和声明放在同一行
格式 lambda [arg1,[arg2,…argN]] : expression
a =lambda x,y :x+y
print(a(3,4))
7
常规 :
def add (x,y)
return x +y
add(10,20)
30
lambda函数
myadd = lambda x,y :x+y
myadd(10,20)
30
——————————————————————————————————————
filter(func,seq) :调用一个布尔函数 func来迭代遍历每个序列中的元素;
返回一个使func返回值为true的元素的序列
.如果布尔函数比较简单,直接使用lambda匿名函数就显得非常方便了
data = filter(lambda x :x %2,[num for num in range(10)])
print(data) #过滤出10以内的奇数
[1,3,5,7,9]
from random import randint
def func1(n):
return n %2
if __name__ == '__main__':
numbs = [randint(1,100) for i in range(10)]
print(numbs)
print(list(filter(func1,numbs)))
print(list(filter(lambda n:n%2,numbs))) #效果一样 可以省略def func1(n)
打印结果:
[29, 82, 30, 10, 60, 15, 100, 93, 88, 66]
[29, 15, 93]
from random import randint
def func1(n):
return n %2
if __name__ == '__main__':
numbs = [randint(1,100) for i in range(10)]
print(numbs)
print(list(filter(func1,numbs)))
print(list(filter(lambda n:n%2,numbs)))
print(list(map(func2,numbs))) #加工一下
print(list(map(lambda n:n+1,numbs))) #组合lambda 使用
##################################################################################################
全局变量 # 从定义开始到程序结束
局部变量 #函数内的变量是局部变量,局部变量当函数调用结束后就消失
global语句 # 局部改变全局的值,
名字空间 # 名字空间,标识符搜索顺序依次是 局部 、全局、和内建
如果两个函数中有同名变量,两个同名变量没有关系
局部变量不会改变全局变量的值
函数作用域 —> 局部 、全局、内建 依次搜索
x = 10
def test2():
global x #声明这里的 x 是全局变量 x
x = "zhangsan"
print(x)
test2()
打印结果:
zhangsan #改变了原本全局变了 x =10
————————————————————————————————————————————
四种形式:
def add(a,b,c,d):
return a+b+c+d
add(10,20,30,40)
add(10,20,30,123) #每次10,20,30 都没有改变可以改以下偏函数
相当于是改造现有函数,将其一部分参数固定下来
from functools import partial
myadd = partial(add,10,20,30)
myadd(5) #得到是10+20+30+5 的值
from operator import add
from functools import partial
add10 = partial(add,10)
print(add10(25)) #得到10+25
35
import tkinter
from functools import partial
root = tkinter.Tk() #相当于创建一个窗体
lb =tkinter.Label(root,text="hello world",font="arial 20")
b1 = tkinter.Button(root,bg="blue",fg="white",text="Button 1")
mybutton = partial(tkinter.Button,root,bg="blue",fg="white") #使用偏函数
b2 = mybutton(text="Button 2")
b3 = mybutton(text="Button 3")
b4 = mybutton(text="Quit",command=root.quit)
for item in [lb,b1,b2,b3,b4]:
item.pack()
root.mainloop()
————————————————————————————————————
如果函数包含了对其自身的调用,该函数就是递归的在操作系统中,
查看某一目录内所有文件、修改权限等都是递归的应用
def func1(n):
if n == 1:
return 1
return n *func1(n-1)
# 5* func(4)
#5*4*func(3)
if __name__ == '__main__':
print(func1(5))
from random import randint
def quick_sort(seq):
if len(seq)<2:
return seq
middle = seq[0]
smaller = []
larger = []
for item in seq[1:]:
if item<middle:
smaller.append(item)
else:
larger.append(item)
return quick_sort(smaller) +[middle]+quick_sort(larger)
if __name__ == '__main__':
nums = [randint(1,100) for i in range(10)]
print(nums)
print(quick_sort(nums))
从句法上讲,生成器是一个带yield语句的函数
一个函数或者子程序只返回一次,但一个生成器能暂停执行并返回一个中间的结果
yield语句返回一个值给调用者并暂停执行
当生成器的 next() 方法被调用的时候,它会准确地从离开地方继续
生成器:
本质上是函数,但是它能生成多个中间值,而函数只有一个最终值
生成器节省内存,更加有效率
ips = ["192.168.1.%s" %i for i in range(1,255)] #方括号是生成列表
print(ips)
hosts = ("192.168.1.%s" %i for i in range(1,255)) #圆括号变成生成器
print(hosts) #得到 at 0x000001A07F3CBCC8>
for host in hosts:
print(host)
生成器通过yield生成多个中间结果
def mygen():
yield 100
print("-------------------")
yield 200
print("####################")
yield 300
a = mygen()
a.__next__() #得到100
a.__next__() #得到200
x = a.__next__() #赋值给x
x #得到300
a.__next__() #没有数据将会抛出StopIteration 异常,生成器对象是一次性的
for item in b: #for 可以遍历生成器,遇到StopIteration 自动停止
print(item)
参考代码:
def file_block(fobj):
content = [ ]
for line in fobj:
content.append(line)
if len(content) == 10: # 10行生成一次
yield content
content.clear() #生成数据交给使用者用清空,以便存 下10行
if content: #如果循环结束后还有数据,生成最后不到10行的内容
yield content
if __name__ == '__main__':
fname = "/etc/passwd"
fobj = open(fname)
for block in file_block(fobj):
print(block)
fobj.close()
——————————————————————————————————————————
闭包将内部函数自己的代码和作用域以及外部函数的作用结合起来
闭包的词法变量不属于全局名字空间域或者局部的–而属于其他的名字空间,带着"流浪"的作用域
闭包对于安装计算,隐匿状态,以及在函数对象和作用域中随意地切换时很有用的
闭包也是函数,但是他们能携带一些额外的作用域
import tkinter
from functools import partial
def pstar():
print("*"*30)
#def hello():
#lb.config(text="Hello China")
#def welcome(): #使用了say_hi 代替
#lb.config(text="hello TEDU")
def say_hi(word):
def greet():
lb.config(text="Hello %s" % word)
return greet
root=tkinter.Tk() #相当于创建一个窗体
lb = tkinter.Label(root,text="Hello World!",font="Arial 20")
MyButton = partial(tkinter.Button,root,bg="blue",fg="white")
b1 = MyButton(text="Button 1",command=pstar)
b2=MyButton(text="Button 2",command=say_hi("China")) #使用闭包函数
b3=MyButton(text="Button 3",command=say_hi("Tedu"))
b4=MyButton(text="Quit",command=root.quit)
for item in [lb,b1,b2,b3,b4]:
item .pack()
root.mainloop()
————————————————————————————————————————
装饰器是在函数调用之上的修饰
这些修饰仅是当声明一个函数或者方法的时候,才会应用的额外调用
使用装饰器的情形有:
-引入日志
-增加计时逻辑来检测性能
-给函数加入事务的能力
def set_color(func):
def set_red():
return "\033[31;1m%s\033[0m" % func()
return set_red()
def hello():
return "Hello World"
@set_color #装饰器使用
def welcome():
return "Hello China"
@set_color
def mytest():
a = 10+10
return a
if __name__ == '__main__':
# print(hello())
# print(welcome())
hello = set_color(hello)
print(hello())
print(welcome())
print(mytest())
######################################################################################
模块支持从逻辑上组织Python代码
当代码量变得相当大的时候,最好把代码分成一些有组织的代码段
代码片相互间有一定的联系,可能是一个包含数据成员和方法的类,
也可能是一组相关但彼此独立的操作函数
·这些代码段是共享的,所以Python允许“调入”一个模块,
允许使用其他模块的属性来利用之前的工作成果,实现代码重用
模块文件
·说模块是按照逻辑来组织Python代码的方法,文件是物理层上组织模块的方法
一个文件被看作是一个独立模块,一个模块也可以被看作是一个文件
模块的文件名就是模块的名字加上扩展名.py
名称空间
·名称空间就是一个从名称到对象的关系映射集合
·给定一个模块名之后,只可能有一个模块被导入到Python解释器中,
所以在不同模块间不会出现名称交叉现象
·每个模块都定义了它自己的唯一的名称空间
四种方式:
import time,os,sys #不推荐推荐,每行导入一个模块
from random import choice ,randint #只导入单个模块,常用
import pickle as p #取别名 ,不太常用
pycharm 可以点code -> optimize import可以优化导入模块(没有用到的模块将会被
移除,导入的模块按字母顺序排序)
导入模块时,Python会到这些位置搜索:
当导入模块时,模块的顶层代码会被执行
一个模块不管被导入(import) 多少次,只会被加载(load)一次
导入包
包是一个有层次的文件目录结构,为平坦的名称空间加入有层次的组织结构
允许程序员把有联系的模块组合到一起
python2.7 中 包目录下必须有一个_init_.py文件
在Python中,目录可以当成特殊的模块,叫作包,导入mods 目录中的hello.py文件可以为
例如
mkdir mods
vim mods/hello.py
hi = "hello world"
import mods.hello
mods.hello.hi
from mods.hello import hi
from mods import hello
hello.hi
hashlib 用来代替md5和sha模块,并使他们的API一致,专门提供hash算法
包括 md5 、sha1、 sha224、 sha256、 sha384 、sha512,使用非常简单方便
加密:
- 对称加密 :加解密使用相同的算法和秘钥 DES/3DES/AES
- 非对称加密: 加解密使用不同的秘钥 RSA/DSA
- 单向加密: 加密只能向一个方向进行,不能通过结果反推回原始数据,MD3/SHA
单向加密用途 :
hashlib:可用于计算MD5值
import hashlib
m = hashlib.md5(b"123456") #接受二进制形式
print(m.hexdigest())
e10adc3949ba59abbe56e057f20f883e
文件生成MD5
with open("/etc/passwd","rb") as fobj:
data = fobj.read()
m = hashlib.md5(data)
print(m.hexdigest())
————————————————————-----
MD5检测
import sys
import hashlib
def check_md5(fname):
m = hashlib.md5()
with open(fname,"rb") as fobj:
while True:
data = fobj.read(4096)
if not data:
break
m.update(data)
return m.hexdigest()
if __name__ == '__main__':
print(check_md5(sys.argv[1]))
###############################################################################################
tarfile 模块允许创建、访问tar文件
同时支持 gzip 、bzip2格式
tarfile: 实现压缩、解压缩、可以调用gzip 、bzip2等
import tarfile
import os
tar = tarfile.open("/tmp/security.tar.gz","w:gz")
os.chdir("/etc")
tar.add("security")
tar.close()
os.mkdir("/tmp/demo")
tar = tarfile.open("/tmp/security.tar.gz","r:gz")
tar.extractall(path="/tmp/demo")
tar.close()
构思——备份:
参考代码:
from time import strftime
import os
import tarfile
import pickle
import hashlib
def check_md5(fname):
m = hashlib.md5()
with open(fname,"rb") as fobj:
while True:
data = fobj.read(4096)
if not data:
break
m.update(data)
return m.hexdigest()
#full_backup 完整备份
def full_backup(folder,dest,md5file):
md5_dict = {} #用于保存每个文件的MD5值{“文件绝对路径” :md5值}
fname = os.path.basename(folder.rstrip("/"))
fname = "%s_full_%s.tar.gz" % (fname,strftime("%Y%m%d"))
fname = os.path.join(dest,fname) #目标文件的绝对路径
tar = tarfile.open(fname,"w:gz") #压缩
tar.add(folder)
tar.close()
for path,folders,files in os.walk(folder):
for file in files:
key = os.path.join(path,file) #拼出绝对路径
md5_dict[file] = check_md5(file) #写入MD5字典
with open(md5file,"wb") as fobj: #字典写入文件
pickle.dump(md5_dict,fobj)
#增量备份
def incr_backup(folder,dest,md5file):
md5_dict={} # 用于保存每个文件的MD5值{“文件绝对路径” :md5值}
fname=os.path.basename(folder.rstrip("/"))
fname="%s_full_%s.tar.gz"%(fname,strftime("%Y%m%d"))
fname=os.path.join(dest,fname) # 目标文件的绝对路径
for path,folders,files in os.walk(folder):
for file in files:
key = os.path.join(path,file) #拼出绝对路径
md5_dict[key] = check_md5(key) #计算当前文件的md5值
with open(md5file,"rb") as fobj:
oldmd5 = pickle.load(fobj) #取出前一天文件MD5值
with open(md5file,"wb") as fobj:
pickle.dump(md5_dict,fobj) #更新文件md5值
tar = tarfile.open(fname,"w:gz")
for key in md5_dict:
if oldmd5.get(key) != md5_dict[key]:
tar.add(key) #新文件,有变化文件进行备份
tar.close()
if __name__ == '__main__':
folder = "/tmp/demo/security"
dest = "/tmp/demo"
md5file = "/tmp/demo/md5file"
if strftime("%a") == "Mon":
full_backup(folder,dest,md5file)
else:
incr_backup(folder,dest,md5file)
类(Class):
用来描述具有相同的属性和方法的对象的集合,它定义了该集合中每个对象所共有的属性和方法。对象是类的实例
实例化:
创建一个类的实例,类的具体对象 。
方法:
类中定义的函数
对象:
通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
使用class 语句来创建一个新类,class之后为类的名称并以冒名结尾
类名建议使用驼峰形式
例:
class BearToy:
pass
游戏人物:
名字、职业、性别、装备、武器 、位置
跳、走、飞、攻击
OOP:面向对象的编程,实现属性和行为的融合统一
calss Hero:
name =
gender =
def run():
move
OOP的更强大方面之一是能够使用一个已经定义好的类,扩展它或者对其进行修改,而不会影响系统中
使用现存的其它代码片段
OOD(面向对象设计)允许类特征在子孙类或子类中进行继承
创建子类
创建子类只需要在圆括号中写明从哪个父类继承即可
class Vendor:
def __init__(self,phone):
self.phone = phone
def dial(self):
print("calling %s" % self.phone)
class BearToy:
def __init__(self,size,color):
"""实例化一个对象时,自动调用"""
self.size = size #bear_big.size = "Large"
self.color = color #bear_big.color = "Brown"
self.vendor = Vendor("400-800-1234") #一个类是另一个类的组件
def sing(self):
print("my color is %s,lalala..." % self.color)
class NewBearToy(BearToy): #子类 括号中填入的是父类、基类
def __init__(self,name,size,color):
# BearToy.__init__(self,size,color): 和下面super功能一样其中一条都可以
super(NewBearToy,self).__init__(size,color)
self.name = name
if __name__ == '__main__':
# bear_big = BearToy("Large","Brown") #实例化,bear_big自动作为第一个参数传递
# vendor=Vendor("400-800-1234")
# print(bear_big.vendor.phone)
# bear_big.vendor.dial()
# print(bear_big.size)
# print(bear_big.color)
# bear_big.sing()
bear2 =NewBearToy("Middle","Brown")
bear2.sing()
Python允许多重继承,即一个类可以是对个父类的子类,子类可以拥有所有的父类的属性
class Foo:
def hello(self):
print("hello world")
class Bar:
def welcome(self):
print("how are you?")
class FooBar(Foo,Bar):
'子类有多个父类,它将继承所有父类的方法'
pass
基本上就是一个函数
在语法上就像一个方法
没有访问对象和它的字段或方法
语法:
使用staticmethod装饰器定义
@staticmethod
静态实例
class Book:
def __init__(self,title,author):
self.title = title
self.author = author
def __str__(self):
return "<<%s>>" % self.title
def __call__(self):
print("<<%s>>is written by %s. " % (self.title,self.author))
if __name__ == '__main__':
core_py = Book("Core Python","Wesley")
print(core_py) #调用 __str__方法
print(core_py()) #调用__call__方法
使用classmethod 装饰器定义
第一个参数cls 表示类本身
class Date:
def __init__(self,year,month,day):
self.year = year
self.month = month
self.day = day
@classmethod
def create(cls,str_date):
"类中的方法,没有实例不能直接调用,需要将其定义为类方法"
year,month,day = map(int,str_date.split("-"))
instance = cls(year,month,day)
return instance
@staticmethod #静态方法
def check_date(cls,str_date):
"相当于和类没有关系,只是把一个函数放到类中"
year,month,day=map(int,str_date.split("-"))
return year<4000 and 1<=month<=12 and 1<=day
if __name__ == '__main__':
d1 = Date(2019,12,15)
print(d1.year)
d2 = Date.create("2020-8-1")
print(d2)
###############################################################################################
import re
m = re.search("f..","seafood")
m.group() #得到 foo
re.findall("f..","seafood is food") # 匹配所有 ,返回列表
["foo","foo"]
re.finditer("f..","seafood is food") #不是直接返回列表,返回的是所有匹配对象的生成器
re.split("\.|-","hello-world.tar.gz") # 以.和- 区分 字符串
["hello","world","tar","gz"]
re.sub("n[a-z]me,"Niu","Hi name,Nice to meet you nbme!")
"Hi Niu, Nice to meet you Niu!"
"Hi name,Nice to meet you nbme!" .replace("name","Niu") #用replace也可以替换
在进行大量匹配的时候,先把模式pattern 编译一下,可以提升效率
patt = re.compile("f..")
m = patt.search("seafood")
m.group()
编写一个Apache日志分析脚本
import re
def count_patt(fname,patt):
cpatt = re.compile(patt)
patt_dict = {}
with open(fname) as fobj:
for line in fobj:
m = cpatt.search(line)
if m:
key = m.group()
patt_dict[key] = patt_dict.get(key,0) +1
return patt_dict
if __name__ == '__main__':
fname = r"D:\a\access_log"
ip = "^(\d+\.){3}\d+"
br = "Chrome|Firefox|MSIE"
print(count_patt(fname,ip))
print(count_patt(fname,br))
————————————————————————————————
import re
from collections import Counter
class CountPatt:
def __init__(self,patt):
self.cpatt = re.compile(patt)
def count_patt(self,fname):
# cpatt=re.compile(patt)
# patt_dict={}
result = Counter()
with open(fname) as fobj:
for line in fobj:
m=self.cpatt.search(line)
if m:
key=m.group()
result.update([key])
# patt_dict[key]=patt_dict.get(key,0) + 1
# return patt_dict
return result
if __name__ == '__main__':
fname=r"D:\a\access_log"
ip="^(\d+\.){3}\d+"
cp = CountPatt(ip)
print(cp.count_patt(fname))
###############################################################################################
使用正则需要导入re模块
import re
记号 | 说明 |
---|---|
. | 匹配任意字符(换行符除外)单单一个字符 |
[…x-y…] | 匹配字符组里的任意字符 |
[^…x-y…] | 匹配不在字符组里的任意字符 |
\d | 匹配任意数字,与[0-9]同义 |
\D | 匹配非数字 |
\w | 匹配任意数字字母字符,与[0-9a-zA-Z]同义 |
\W | 匹配非任意数字字母字符 --空格和符号 |
\s | 匹配空白字符,与[\r\v\f\t\n] 同义 |
\S | 匹配非空白字符 |
测试
在vim里面 输入 / 加内容 例如 /\D 匹配非数字
搜索tm字符内容
/t.m
/t[0-9a-z]m
/\W
/t[-a0]m
/t[0-9^]m #和/t[^0-9]m 意义一样,取反
记号 | 说明 |
---|---|
literal | 匹配字符串的值 |
re1 | re2 |
* | 匹配前面出现的正则表达式零次或多次 |
+ | 匹配前面出现的正则表达式一次或多次 |
? | 匹配前面出现的正则表达式零次或一次 |
{M,N} | 匹配前面出现的正则表达式至少M次最多N次 |
例如:
/tam\|t8m
/t\{3,5\}m
/t\{3,\}
/t\?m
/t\+m
记号 | 说明 |
---|---|
^ | 匹配字符串的开始 |
$ | 匹配字符串的结尾 |
\b | 匹配单词的边界 |
() | 对正则表达式分组 |
\nn | 匹配已保存的子组 |
data = "His phone number is : 150889912"
m = re.search(".+|(\d+\)",data) #默认+ 或者 * 都是贪婪匹配
m.group() #总是返回整个模式匹配到的内容
"His phone number is : 150889912"
m.group(1)
"2"
m = re.search(".+?|(\d+\)",data) # ? 可以取消贪婪匹配
m.group()
"His phone number is : 150889912"
m.group(1)
"150889912"
————————————————————————————————————————
import re
re.match("f..","food") #如果匹配到,返回一个匹配对象
print(re.match("f","seafood")) #没有匹配到,返回None
m = re.match("f..","food')
m.group()
套接字是一种具有“通讯端点” 概念的计算机网络数据结构
家族名为 AF_UNIX
基于网络的 ,家族名 为 AF_INET
无论你使用哪一种地址家族,套接字的类型只有两种。
TCP
面向连接的主要协议就是传输控制协议TCP ,套接字类型为 SOCK_STREAM
UDP
无连接的主要协议是用户数据报协议UDP ,套接字类型为 SOCK_DGRAM
Python中使用socket模块中的socket函数实现套接字的创建
Python中所有的字符有:str类型和bytes类型
str类型转换为bytes类型 ( encode 和 decode )
a = "你好"
type(a)
<class "str">
a.encode() #将str 转换为bytes
b'xe4\xbd\xa0\xe5\xa5\xbd'
b = b"Hello"
tyep(b)
<class "bytes">
b.decode() #将bytes转换为str
面向连接的主要协议就是 传输控制协议 TCP ,
套接字类型: SOCK_STREAM
创建TCP服务器的主要步骤如下:
参考代码
import socket
host = "" #代表0.0.0.0
port = 12345 #应该大于1024
addr = (host,port)
s = socket.socket() #默认使用TCP协议
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #设置套接字选项,使得服务程序结束后立即再启动
s.bind(addr)
s.listen(1) #一般只能写到5以内,表示允许多少客户端排队访问
cli_sock,cli_addr = s.accept()
print("客户端:",cli_addr)
data = cli_sock.recv(1024) #相当于fobj.read(1024)
print(data)
print(data.decode())
sdata = "欢迎!\r\n"
cli_sock.send(sdata.encode()) #发送的数据必需是bytes类型,二进制
cli_sock.close()
s.close()
创建TCP 客户端的步骤主要如下 :
参考代码
import socket
host = "127.0.0.1"
port = "12345"
addr = (host,port)
c = socket.socket()
c.connect(addr)
c.send(b"Hello World!\r\n")
data = c.recv(1024)
print(data.decode(),end="")
c.close()
无连接的主要协议是用户 数据报协议 UDP ,
套接字类型: SOCK_DGRAM
创建UDP服务器的主要步骤如下:
参考代码
import socket
host = ""
port = 12345
addr = (host,port)
s = socket.socket(type=socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind(addr)
data,cli_addr = s.recvfrom(1024)
print(data.decode(),end="")
s.sendto(b"How are you?\r\n",cli_addr)
s.close()
创建UDP客户端的步骤主要如下:
参考代码
import socket
host = ""
port = 12345
addr = (host,port)
c = socket.socket(type=socket.SOCK_DGRAM)
c.sendto(b"Nice to meet you!\r\n",addr)
data,ser_addr = c.recvfrom(1024)
print(data.decode())
c.close()
为了实现不间断接收信息
import socket
host = ""
port = 12345
addr = (host,port)
s = socket.socket(type=socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind(addr)
while True:
data,cli_addr = s.recvfrom(1024)
print(data.decode(),end="")
s.sendto(b"How are you?\r\n",cli_addr)
s.close()
import socket
host = ""
port = 12345
addr = (host,port)
c = socket.socket(type=socket.SOCK_DGRAM)
while True:
sdata = input(">")+"\r\n"
if sdata.strip() == "quit":
break
c.sendto(b"Nice to meet you!\r\n",addr)
data,ser_addr = c.recvfrom(1024)
print(data.decode())
c.close()