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()