set集合

集合是一个无序的、不可重复的集合。主要作用有:

1.去重,把一个列表变成集合,就等于去重了。
2.关系测试,测试两组数据之前的交集、差集、并集等关系

常用操作

创建、交集、并集、差集、对称差集、子集、父集 长度、判断元素是否在集合中、删除

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 创建集合:
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.关闭文件

基本操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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语句:

1
2
3
4
5
6
7
8
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

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/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中:

1
2
3
4
5
6
7
8
在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),也就是如何编写程序的方法论。
它属于"结构化编程"的一种,主要思想是把运算过程尽量写成一系列嵌套的函数调用

函数的基本语法及特征

定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可
函数的特征:
减少重复代码
使程序变的可扩展
使程序变得易维护

函数的定义:

语法:

1
2
def function():
     print("in the function")

还可以传递参数:

1
2
3
def Sum(x,y):
     sum = x +y
     return sum

形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量
实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值。

 位置参数和关键字参数、默认参数、可变参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/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

在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。
当全局变量与局部变量同名时:
在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/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声明,但是在以后的工作中禁用。

递归

在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数

1
2
3
4
5
6
7
8
9
10
11
12
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)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

高阶函数

变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数

1
2
3
4
5
def add(x,y,f):
    return f(x) + f(y)
 
res = add(3,-6,abs)
print(res)

 作业1:用python实现简答的sed替换功能

 ReadMe:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
这个一个使用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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 这个一个关于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 即可。

  程序流程图:

程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#!/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()