set集合
集合是一个无序的、不可重复的集合。主要作用有:
1.去重,把一个列表变成集合,就等于去重了。
2.关系测试,测试两组数据之前的交集、差集、并集等关系
常用操作
创建、交集、并集、差集、对称差集、子集、父集 长度、判断元素是否在集合中、删除
# 创建集合:
set1 = set([1,2,3,4,5,90])
set2 = set([2,378,98])
# 交集 (在set1和set2中都有的元素)
print(set1.intersection(set2))
print(set1&set2)
# 并 set1和set2的所有元素的集合
print(set1.union(set2))
print(set1|set2)
# 差集 :在set1中不在set2中
print(set1.disfference(set2))
print(set1-set2)
# 对称差集 项在t或s中,但不会同时出现在二者中
print(set1^set2)
print(set1.symmetric_difference(set2))
# 子集
print(set1.issubset(set2))
# 父集
print(set1.issuperset(set2))
# 在set中添加一项
print(set1.add(45))
# 在set 中添加多项
print(set1.update(set2))
# remove删除指定项,若不存在,会报错
print(set1.remove(2))
print(set1.discard(2)) # remove删除指定项,如不存在,不报错
print(set1.pop()) # 删除任意一项
set1.discard(98)
# 集合的长度
print(len(set1))
x = ''
if x in set1:# 判断 x是否在set1 中。
pass
if x not in set1:# 判断集合不在set1中。
pass
if set1.issubset(set2): # s <= t 测试是否s中的每一个元素都在t中
pass
文件操作
对文件的操作流程:
1.打开文件,得到文件句柄并赋值给一个变量
2.通过句柄对文件进行操作
3.关闭文件
基本操作:
f = open("yesterday",'r',encoding='utf-8') # 只可读
f2 =open("yesterday2",'w',encoding="utf-8") # 可写,覆盖原来的内容
f3=open("yesterday2",'a',encoding="utf-8") # 追加不可读
data = f.read() # 打印所有内容
f2.write("我爱北京*\n")
f2.write("*\n")
f4 = open("yesterday","a+",encoding='utf-8') # 新建文件
print(f4.readline()) #
print(f4.readline()) # 读一行
print(f4.encoding) # 打印文件句柄的编号方式
print(f4.tell()) # 显示当前文件句柄的位置
print(f4.seek(10)) # 件句柄调到第10个位置,
# 备注:在写文件时,如果使用r+ ,w+,时,不使用seek时,在文件末尾追加写入的内容
# 若使用,seek(),就覆盖写入了,不在使用追加模式
f4.truncate(10) # 从文件开头到10 截断
f4.flush() # 将数据由内存刷入到文件或者硬盘
print(f4.readline())
for line in f4:
print(line) # 只在内存中保存一行
f5 = open("test.txt",'rb')
print(f5.readline())
f5.close()
打开文件的模式有:
r,只读模式(默认)。
w,只写模式。【不可读;不存在则创建;存在则删除内容;】
a,追加模式。【可读; 不存在则创建;存在则只追加内容;】
"+" 表示可以同时读写某个文件
r+,可读写文件。【可读;可写;可追加】
w+,写读
a+,同a
with语句:
python 2.7中
with open('log','r') as f:
for line in f:
print(line)
python3中:
with open('log1') as obj1, open('log2') as obj2:
pass
编码方式
在python2中,默认编码是ASSIC编码,若在文件中指定文件的编码方式为“utf-8",若想转化成gbk,需要先解码为unicode,转编码为gbk
例如:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
#author luotianshuai
import chardet
tim = '你好'
print chardet.detect(tim)
#先解码为Unicode编码,然后在从Unicode编码为GBK
new_tim = tim.decode('UTF-8').encode('GBK')
print chardet.detect(new_tim)
#结果
'''
{'confidence': 0.75249999999999995, 'encoding': 'utf-8'}
{'confidence': 0.35982121203616341, 'encoding': 'TIS-620'}
python3中:
在python3中,默认的就是unicode
# author:snate
tim =u"你好"
new_tim = tim.encode('GBK')直接编码就可以。
print(new_tim)
new_time=tim.encode("GBK").decode("GBK").encode("GB2312")
print(new_tim)
面向对象、面向过程、函数式编程
面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
简单说,"函数式编程"是一种"编程范式"(programming paradigm),也就是如何编写程序的方法论。
它属于"结构化编程"的一种,主要思想是把运算过程尽量写成一系列嵌套的函数调用
函数的基本语法及特征
定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可
函数的特征:
减少重复代码
使程序变的可扩展
使程序变得易维护
函数的定义:
语法:
def function():
print("in the function")
还可以传递参数:
def Sum(x,y):
sum = x +y
return sum
形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量
实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值。
位置参数和关键字参数、默认参数、可变参数
#!/usr/bin/env python
# _*_ encoding:utf-8 _*_
# author:snate
# 位置参数和关键字参数
def test(x,y,z):
print(x,y,z)
# 默认参数
def test2(sex,name="alex",age=12):
print(sex,name,age)
# 参数个数不固定的形式参数
def test3(name,*args):
print(name,args)
def test4(name,**kwargs):
print(name,kwargs)
test(1,2,3) # 位置参数:实参和形参必须一一对应
test(x=1,y=2,z=2)
test(x=1,z=2,y=2) # 关键字参数与位置无关,不必一一对应
test2("女",age=25,name=12) # 默认参数必须放到后面,
test3("gxw",1,1,23,4,["nihao",2,3,5]) #*args 会把多传入的多个参数变成一个元组形式
test3("gxw",*[1,2,3,4,5]) # *args 会把多传入的参数变成一个元组形式
test4(name="alex",age=12,sex="f",id=1) # *kwargs 会把多传入的关键字参数变成一个dict形式
'''
1 2 3
1 2 2
1 2 2
女 12 25
gxw (1, 1, 23, 4, ['nihao', 2, 3, 5])
gxw (1, 2, 3, 4, 5)
alex {'id': 1, 'sex': 'f', 'age': 12}
'''
return
在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。
当全局变量与局部变量同名时:
在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用
#!/usr/bin/env python
# _*_ encoding:utf-8 _*_
# author:snate
school = "oldboy Edu."
name = "alec"
def test1(name):
print("修改前:"+name)
name = "alex"
print("修改后:"+name)
global school
school = "MaGe"
print(school)
test1(name)
print(school)
备注:为了在函数中修改全局变量的值,需要global声明,但是在以后的工作中禁用。
递归
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数
def calc(n):
print(n)
if int(n/2) ==0:
return n
return calc(int(n/2))
calc(10)
'''
10
5
2
1
'''
递归的特征:
递归特征:
1. 必须有一个明确的结束条件
2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
高阶函数
变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数
def add(x,y,f):
return f(x) + f(y)
res = add(3,-6,abs)
print(res)
作业1:用python实现简答的sed替换功能
ReadMe:
这个一个使用python实现简单sed功能的程序
个人介绍
name:Gaoxuewu
nickName:snate
blog_addr: http://www.cnblogs.com/itlinux/p/5749369.html
项目需求
利用python实现shell中的sed的简单替换功能
功能介绍
将文件打开,一行一行的读,判断每行中,是否存在要替换的字符,若存在就替换 将替换后的行写入到新的文件;若不存在直接将读出的行写入到另一个文件。
环境依赖
python3.*
window/linux os
os模块
sys模块
目录结构
testSed
├── __init__.py
├── README.md # 程序介绍
├── testSed FlowChart # 程序流程图
├──yesterday # 需要读取的文件
├── yesterday.bak #替换之前,文件的备份
运行说明
在搭建好的python环境中,运行python testshell.py "年少轻狂" "Alex 很狂",就能实现用"Alex 很狂"替换"年少轻狂"的功能。
流程图:
程序:
#!/usr/bin/env python
# _*_ encoding:utf-8 _*_
# author:snate
'''
将yesterday文件中的“年少轻狂”替换成“alex 很狂"
'''
from sys import argv
import os
f1 = open("yesterday", "r", encoding="utf-8")
f2 = open("yesterday.bak", "w", encoding="utf-8")
for line in f1:
if argv[1] in line: #"年少轻狂"
line = line.replace(argv[1], argv[2]) # "---》alex 很狂"
f2.write(line)
f1.close()
f2.close()
os.rename("yesterday","yesterday-bak")
os.rename("yesterday.bak","yesterday")
作业2:查找、修改、增加和删除proxy的内容
Readme:
# 这个一个关于proxy配置文件增、删、查的程序
### 个人介绍
* name:Gaoxuewu
* nickName:snate
* email:hangtiangazi@163.com
* blog_addr:http://www.cnblogs.com/itlinux/p/5749369.html
### 功能介绍
* 查询时,输入域名,显示域名的相关的backend的信息
* 删除时,输入域名,能够删除域名以及配置服务器相关的信息
* 增加时,需要输入配置信息的字典,字典中包含backend的域名信息,以及包含IP,Maxconn,server的record列表
1.例如:输入内容为:修改需输入内容举例:{"backend": "test.oldboy.org","record":{"server": "100.1.7.9","weight": 20,"maxconn": 30}}
程序会自动判断输入的格式是否正确,若不正确,提示用户重新输入,直到输入正确的格式。
2.根据输入的内容的backend的域名,判断域名是否不在,不存在,添加域名,和需要配置的服务器信息;
3.若域名存在,判断域名的服务器信息是否存在,若不在提供用户信息已存在,不需要修改文件;若不存在,
在域名信息后面增加该信息。
### 环境依赖:
* python3以上版本
* linux/windows os
* sys 模块
* os 模块
* time模块
###目录结构:
testProxy
├── __init__.py
├── README.md # 程序介绍
├── testProxy FlowChart # 程序流程图
├──proxy # proxy 配置文件
├── proxy.bak_.... proxy的备份文件
├── proxy.log # 日志文件
├── tetsProxy.py # 程序
├──search_backend(search_domain_name) # 查找域名信息
├──input_format(add_domain_info_str) # 判断输入域名及服务器的配置信息是否正确
├──add_backend() # 添加域名信息
├──dek_backend(del_domain_name) # 删除域名相关信息
├──main() #主程序
### 运行说明
在搭建好的python环境中,运行python testProxy.py 即可。
程序流程图:
程序:
#!/usr/bin/env python
# _*_ encoding:utf-8 _*_
# author:snate
# 通过域名查询proxy的函数
import json
import time
import os
time_fort1 = "%Y-%m-%d %H:%M:%S"
time_fort2 = "%Y-%m-%d-%H-%M-%S"
current_time = time.strftime(time_fort1)
bak_time = time.strftime(time_fort2)
# 查找函数,根据输入的域名,返回域名的详细信息
def search_backend(search_domain_name):
'''
:param : Domain name
:return: the specific information of Daomain ,Fomat:list
'''
f = open("proxy",'r',encoding="utf-8")
info_list=[]
Flag = 0 # 设置标志位 默认值为0 表示为匹配
for line in f:
line = line.strip() # 去掉两端的空格和换行
if line == "backend %s" % search_domain_name:
Flag = 1 # 若匹配上默认值为1
elif line.startswith("backend"):
Flag = 0
elif Flag == 1 and len(line) != 0: # 接着循环,将doamain的信息保存到info_list中。
info_list.append(line)
f.close()
return info_list
# 判断输入的的域名信息及服务器的配置信息是否正确
def input_format(add_domain_info_str):
'''
:param add_domain_info_str:
:return: boolean
'''
add_domain_content = json.loads(add_domain_info_str)
try:
add_domain_name = add_domain_content["backend"]
add_domain_server = add_domain_content["record"]["server"]
add_domain_weight = add_domain_content["record"]["weight"]
add_domain_maxconn = add_domain_content["record"]["maxconn"]
except:
return False
else:
return True
# 添加域名信息
def add_backend():
'''
:return: None
'''
while True:
add_domain_info_str = input("请输入用户要增加的配置信息:")
Fort_Flag = input_format(add_domain_info_str)
if Fort_Flag :
add_domain_content = json.loads(add_domain_info_str)
add_domain_name = add_domain_content["backend"]
add_domain_server = add_domain_content["record"]["server"]
add_domain_weight = add_domain_content["record"]["weight"]
add_domain_maxconn = add_domain_content["record"]["maxconn"]
add_domain_server_info = "server %s %s weight %s maxconn %s "%(add_domain_server,add_domain_server,\
add_domain_weight,add_domain_maxconn)
info_list = search_backend(add_domain_name)
if len(info_list) == 0:
with open("proxy","r",encoding="utf-8") as proxy_read, \
open("new_proxy","w",encoding="utf-8") as proxy_bak_write:
content_list = proxy_read.readlines()
content_list.append("\n")
content_list.append("backend %s\n" %add_domain_name)
content_list.append("%s %s" % (8*" ", add_domain_server_info))
proxy_bak_write.writelines(content_list)
# 提示用户没有域名信息,将配置信息添加到配置文件最后
print("No domain name,We will add to the end of the proxy!")
time.sleep(1)
print('''\033[31;1mInformation has been added successly!!!!\033[0m''')
os.rename("proxy","proxy.bak_%s" % bak_time)
os.rename("new_proxy", "proxy")
with open("proxy.log", 'a+',encoding='utf-8') as log_write:
log_write.write("%s ad d the %s into proxy config successfully!\n" %(current_time,add_domain_server_info))
else:
if add_domain_server_info in info_list: # 若服务器信息重叠,提示用户信息重叠,不需要配置文件
print("\033[31;1mServer_info:%s is existed!,don't need add!!!!\033[0m" % add_domain_server_info)
else:
info_list.append(add_domain_server_info)
with open("proxy", 'r', encoding='utf-8') as proxy_read, \
open("proxy_bak", 'w', encoding='utf-8') as proxy_bak_write:
begin_Flag = 0 # 设置获取目标内容的flag标志
end_Flag = 0 # 设置限制目标内容循环的标志
for line in proxy_read.readlines():
if line.strip() == "backend %s" % add_domain_name: # 若其中一行的内容为“backend domain_name",更改获取内容表示符的值为1
begin_Flag = 1
# 更改获取表示符之后,继续循环表示列表,若碰到以“backend”开头的行,重新将开始标志位设置为0
elif line.strip().startswith("backend"):
begin_Flag = 0
if begin_Flag == 0: # 若获取内容的表示符为0 表示非目标内容,直接写入到proxy_bak文件。
proxy_bak_write.writelines(line);
elif begin_Flag == 1 and end_Flag == 0:
proxy_bak_write.write("backend %s\n" % add_domain_name)
for index,domain_info in enumerate(info_list):
info_list[index] == '%s%s\n'%(8*" ",domain_info)
proxy_bak_write.writelines(info_list)
proxy_bak_write.write('\n') # 最后加一个空白行
end_Flag = 1 # 设置限制目标内容表示符为1
os.rename("proxy", "proxy.bak_%s" % bak_time)
os.rename("proxy_bak", "proxy")
with open("proxy.log", "a+",encoding='utf-8') as log_write:
log_write.write("%s add the %s into %s proxy config\n" % (current_time, add_domain_server_info,\
add_domain_name))
break
else:
print("您输入的格式不正确,请重新输入!")
# 删除域名信息
def del_backend(del_domain_name):
'''
:param del_domain_name:
:return: None
'''
with open("proxy", 'r', encoding='utf-8') as proxy_read, \
open("proxy_bak", 'w',encoding='utf-8') as proxy_bak_write:
begin_Flag = 0
for line in proxy_read.readlines():
line = line.strip()
if "backend %s" %del_domain_name == line:
begin_Flag == 1
elif line.startswith("backend"):
begin_Flag = 1
if begin_Flag == 0 :
proxy_bak_write.write(line)
with open("proxy.log",'a+',encoding='utf-8') as log_write:
log_write.write("%s del the %s info!\n"% (current_time, del_domain_name))
os.rename("proxy","proxy.bak_%s" %(bak_time))
os.rename("proxy.bak","proxy")
print("%s's info is successfully deleted!" % del_domain_name)
# 主程序
def main():
'''
:return: none
'''
while True:
print('''
1.查询
2.增加
3.删除
4.退出
''')
user_choose = input("请输入您的选择:")
if user_choose.isdigit():
user_choose = int(user_choose)
if user_choose == 1:
search_domain_name = input("请输入您要查询详细的域名:")
info_list = search_backend(search_domain_name)
if len(info_list) == 0:
print("The info of %s don't exist" % search_domain_name)
else:
for line in info_list:
print('\033[31;1m%s\033[0m' % line)
elif user_choose == 2:
add_backend()
elif user_choose == 3:
del_domain_name = input("input the domain name you want to delete:")
info_list = search_backend(del_domain_name)
if len(info_list) == 0:
print("要删除的域名信息不存在,不执行任何操作!")
else:
del_backend(del_domain_name)
elif user_choose == 4:
for i in range(3):
print("程序在\033[31;1m[%s]\033[0m秒后退出!" % (3-i))
time.sleep(1)
exit()
else:
print("您的输入有误,请重新输入:")
main()