〇、上集回顾
字符编码:ascii-unicode-utf8
传入参数:sys模块,与python解释器相关
字符串相加,字符串本质是c数组,在内存中为连续的空间
基本数据类型:一切事物都是对象,对象都由类创建,对象的方法都是类中成员
int、str、tuple、list、dict
一、集合:set
元组和列表中的元素可以重复,set中不允许
可以作为爬虫缓存使用
优势:
-
访问速度快
-
原生解决去重问题
新建set或者更新set
>>> s1 = set() #创建一个新的set
>>> s1.add('alex') #增加一个元素
>>> print(s1)
{'alex'}
>>> s1.update(['alex','eric']) #增加多个元素
>>> print(s1)
{'eric', 'alex'}
差集:
>>> s2 = set(['alex','alex'])
>>> s2
{'alex'}
>>> s2 = set(['alex','alex','eric','tony'])
>>> s2
{'eric', 'tony', 'alex'}
>>> s3 = s2.difference(['alex','eric']) #检查差异,生成了一个新的set
>>> s3
{'tony'}
>>> s2.difference(['alex','eric'])
{'tony'}
>>> s2
{'eric', 'tony', 'alex'}
>>> s4 = s2.difference_update(['alex','eric']) #检查差异,修改原来的set
>>> s4
>>> s2
{'tony'}
取交集
>>> s1 = set([11,22,33,44])
>>> s2 = set([33,44,55])
>>> s3 = s1.intersection(s2) #取交集,形成一个新的set,如&运算符
>>> s3
{33, 44}
>>> s1
{33, 11, 44, 22}
>>> s4 = s1.intersection_update(s2) #取交集,更新原来的set
>>> s4
>>> s1
{33, 44}
>>> s1.isdisjoint(s2) #是否有交集,没有交集返回True,有交集返回False
False
>>>
子集或父集
>>> s1
{33, 44}
>>> s2
{33, 44, 55}
>>> s1.issubset(s2) #是否为子集(包含于),是返回True
True
>>> s2.issuperset(s1) #是否为父集(包含),是返回True,
True
>>>
移除:
pop #将删除的作为返回值
remove #无返回值
>>> s1
{33, 44}
>>> s2
{33, 44, 55}
>>> s3 = s1.pop() #随机删除一个值,并返回这个值
>>> s3 #这里删除了‘33’
33
>>> s1 #
{44}
>>> s4 = s2.remove(33) #指定删除某个元素,不返回值
>>> s4 #返回值为空
>>> s2
{44, 55}
对称差集与并集
ret1 = s1.difference(s2)
ret2 = s1.symmetric_difference(s2)
>>> s1 = set([11,22,33])
>>> s2 = set([22,44])
>>> ret1 = s1.difference(s2) #差集,返回不包含与s2中的s1元素,等价于s1-s2
>>> ret1
{33, 11}
>>> s1-s2
{33, 11}
>>> ret2 = s1.symmetric_difference(s2) #对称差集,返回两个set中不同元素的合集,等价于(s1|s2)-(s1&s2)
>>> ret2
{33, 11, 44}
>>> (s1|s2)-(s1&s2)
{33, 11, 44}
>>> ret3 = s1.union(s2) #求并集,等价于s1|s2
>>> ret3
{33, 11, 44, 22}
>>> s1|s2
{33, 11, 44, 22}
简单的例子(寻找差异):
# 数据库中原有
old_dict = {
"#1":{ 'hostname':c1, 'cpu_count': 2, 'mem_capicity': 80 },
"#2":{ 'hostname':c1, 'cpu_count': 2, 'mem_capicity': 80 },
"#3":{ 'hostname':c1, 'cpu_count': 2, 'mem_capicity': 80 }
}
# cmdb 新汇报的数据
new_dict = {
"#1":{ 'hostname':c1, 'cpu_count': 2, 'mem_capicity': 800 },
"#3":{ 'hostname':c1, 'cpu_count': 2, 'mem_capicity': 80 },
"#4":{ 'hostname':c2, 'cpu_count': 2, 'mem_capicity': 80 }
}
- 需求:
1.原来没有的-新增
2.原有有的-更新
3.原来有的新的没有-原来删除
- 结果:
1. 要更新的数据
2. 要删除的数据
3. 要增加的数据
代码:
# 数据库中原有
old_dict = {
"#1":{ 'hostname':c1, 'cpu_count': 2, 'mem_capicity': 80 },
"#2":{ 'hostname':c1, 'cpu_count': 2, 'mem_capicity': 80 },
"#3":{ 'hostname':c1, 'cpu_count': 2, 'mem_capicity': 80 }
}
# cmdb 新汇报的数据
new_dict = {
"#1":{ 'hostname':c1, 'cpu_count': 2, 'mem_capicity': 800 },
"#3":{ 'hostname':c1, 'cpu_count': 2, 'mem_capicity': 80 },
"#4":{ 'hostname':c2, 'cpu_count': 2, 'mem_capicity': 80 }
}
s1 = set(old_dict.keys())
s2 = set(new_dicr.keys())
#取交集,可能要更新,可能不动
s3 = s1.intersection(s2)
#删除的元素,
s4 = s1.difference(s2)
#增加的元素
s5 = s2.difference(s1)
可以用方法实现,也可以使用运算符来实现
>>> s1 = set([1,2,3])
>>> s2 = set([1,3,4])
>>> #取交集,可能要更新,可能不动
... s3 = s1.intersection(s2)
>>> #删除的元素,
... s4 = s1.difference(s2)
>>> #增加的元素
... s5 = s2.difference(s1)
>>> s3
{1, 3}
>>> s4
{2}
>>> s5
{4}
>>>
>>> s1|s2
{1, 2, 3, 4}
>>> s1 & s2
{1, 3}
>>> s1 - s2
{2}
>>> s2 -s1
{4}
>>>
二、collections系列
使用需要导入,import collections
1、counter:继承dict,计数器
import collections
c1 = collections.Counter('asdcasdqasdaacasaasasdqqasd')
print(c1)
c2 = c1.most_common(4) #前四位
print(c2)
# for i in c1.elements(): #print 所有对象,原生的值
# print(i)
c3 = dict(c1) #转化为字典
print(c3)
for k,v in c1.items(): #计数器也具备dict的方法items,keys,values,
print(k,v) #循环的处理完后的数据
执行结果:
Counter({'a': 10, 's': 7, 'd': 5, 'q': 3, 'c': 2}) #奇怪的对象
[('a', 10), ('s', 7), ('d', 5), ('q', 3)]
{'c': 2, 'd': 5, 'a': 10, 'q': 3, 's': 7}
c 2
d 5
a 10
q 3
s 7
fromkeys #这个方法没有定义,忽略
import collections
obj = collections.Counter([11,22,22,33,44])
print(obj)
obj.update([11,'eric'])
print(obj)
obj.subtract([55,11]) #delete,会出现-1
print(obj)
执行结果:
Counter({22: 2, 33: 1, 11: 1, 44: 1})
Counter({11: 2, 22: 2, 33: 1, 'eric': 1, 44: 1})
Counter({22: 2, 33: 1, 'eric': 1, 11: 1, 44: 1, 55: -1})
2、有序字典(OrderedDict)
如何实现一个有序的字典,可以使用一个原有的无序字典+一个列表,使用列表来维护key
3、默认字典(defaultdict)
defaultdict是对字典的类型的补充,他默认给字典的值设置了一个类型。
import collections
obj2 = collections.defaultdict(list)
obj2['k1'].append('v1')
print(obj2)
执行结果:
defaultdict(<class 'list'>, {'k1': ['v1']})
4、可命名元组
根据nametuple可以创建一个包含tuple所有功能以及其他功能的类型。
import collections
MyTupleClass = collections.namedtuple('MyTupleClass', ['x', 'y', 'z'])
obj = MyTupleClass(11, 22, 33)
print(obj.x,obj.y,obj.z)
执行结果:
11 22 33
5、队列
双向队列:首尾可取可放
import collections
obj = collections.deque()
obj.append('1')
obj.appendleft('2')
obj.append('1')
print(obj)
c = obj.count('1')
print(c)
obj.extend(['2','2'])
obj.extendleft(['1','2'])
print(obj)
执行结果:
deque(['2', '1', '1'])
2
deque(['2', '1', '2', '1', '1', '2', '2'])
单向队列:先进先出
import queue
q = queue.Queue()
# q.qsize()
# q.full()
q.put('1')
print(q.get())
执行结果:
1
三、深浅拷贝
#导入模块
import copy
#浅拷贝,更加节约内存
copy.copy()
#深拷贝
copy.deepcopy()
针对数字和字符串:深拷贝和浅拷贝都不会改变内存ID
>>> a = 123
>>> b = 123
>>> id(a),id(b) #缓存
(4297541856, 4297541856)
>>> import copy
>>> b = copy.copy(a) #浅拷贝没有改变内存ID
>>> id(a),id(b)
(4297541856, 4297541856)
>>> c = copy.deepcopy(a) #深拷贝也没有改变内存ID
>>> id(a),id(c)
(4297541856, 4297541856)
针对其他类型:如字典,列表中的多层嵌套,浅拷贝和深拷贝将有所不同
>>> n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]}
>>> n2 = n1
>>> id(n1),id(n2) #两个字典指向同一个ID
(4303008072, 4303008072)
>>> n3 = copy.copy(n1) #浅拷贝
>>> id(n1),id(n3) #字典的id已经不同,说明浅拷贝开辟了新的内存空间
(4303008072, 4312709384)
>>> id(n1['k3']) #但是字典中的列表ID还是没有改变,说明对字典中的列表没有作拷贝
4313460872
>>> id(n3['k3'])
4313460872
>>> n4 = copy.deepcopy(n1) #深拷贝
>>> id(n1),id(n4) #字典的id已经不同,说明深拷贝开辟了新的内存空间
(4303008072, 4312707144)
>>> id(n4['k3']) #字典中的列表也已经改变,说明深拷贝针对字典中的列表也进行了拷贝
4313524744
>>> id(n1['k3'])
4313460872
>>>
深拷贝和浅拷贝的区别,以服务器监控模板的拷贝为例:
import copy
dic = {
'cpu':[80,],
'mem':[80,],
'disk':[80,]
}
new_dic = copy.copy(dic)
new_dic['cpu'][0] = 50
print(dic)
print(new_dic)
执行结果:
{'cpu': [50], 'disk': [80], 'mem': [80]}
{'cpu': [50], 'disk': [80], 'mem': [80]}
import copy
dic = {
'cpu':[80,],
'mem':[80,],
'disk':[80,]
}
new_dic = copy.deepcopy(dic)
new_dic['cpu'][0] = 50
print(dic)
print(new_dic)
执行结果:
{'cpu': [80], 'disk': [80], 'mem': [80]}
{'cpu': [50], 'disk': [80], 'mem': [80]}
四、函数
1、函数的定义和使用
函数的定义主要有如下要点:
-
def:表示函数的关键字
-
函数名:函数的名称,日后根据函数名调用函数
-
函数体:函数中进行一系列的逻辑计算,如:发送邮件、计算出 [11,22,38,888,2]中的最大数等...
-
参数:为函数体提供数据
-
返回值:当函数执行完毕后,可以给调用者返回数据。
def mail():
n = 123
n += 1
print(n)
mail() #执行函数
f = mail #内存地址指向f
f() #同样可以执行函数
执行结果:
124
124
1)返回值
return
- 返回值,返回啥都行,如果没有使用return默认返回None
#举例:发送邮件
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
def mail():
ret = True
try:
msg = MIMEText('邮件内容', 'plain', 'utf-8')
msg['From'] = formataddr(["武沛齐",'wptawy@126.com'])
msg['To'] = formataddr(["走人",'389285205@qq.com'])
msg['Subject'] = "主题"
server = smtplib.SMTP("smtp.126.com", 25)
server.login("wptawy@126.com", "邮箱密码")
server.sendmail('wptawy@126.com', ['389285205@qq.com',], msg.as_string())
server.quit()
except Exception:
ret = False
return ret #返回值
ret = mail()
if ret:
print('发送成功')
else:
print('发送失败')
- 遇到return,函数结束不再执行,中断函数操作
#举例:(使用pycharm的断点调试)
def show():
print('a')
if 1 == 1:
return [11,22] #中断函数
print('b')
ret = show()
2)参数
#没有参数
def show():
print('a')
show()
#两个参数
def show1(a,b):
print(a,b)
show1(1,2)
#默认参数,必须写在后面
def show2(a,b=200):
print(a,b)
show2(100)
show2(100,180)
#指定参数
def show3(a,b):
print(a,b)
show3(b=100,a=200)
函数使用动态参数:
def show1(*args): #转化为元组
print(args,type(args))
show1(11,22,33,44,55,212)
def show2(**kwargs): #转化为字典
print(kwargs,type(kwargs))
show2(n1 = 123,n2 = 32)
def show3(*args,**kwargs): #编写有顺序,传入参数时候也有顺序
print(args,type(args))
print(kwargs,type(kwargs))
show3(11,22,3,4,55,n1=23,n2=123)
执行结果:
(11, 22, 33, 44, 55, 212) <class 'tuple'>
{'n1': 123, 'n2': 32} <class 'dict'>
(11, 22, 3, 4, 55) <class 'tuple'>
{'n1': 23, 'n2': 123} <class 'dict'>
def show3(*args,**kwargs):
print(args,type(args))
print(kwargs,type(kwargs))
show3(11,22,3,4,55,n1=23,n2=123)
#另外一种方法传入多个参数
l = [11,22,3,4,55]
d = {'n1':23,'n2':123}
show3(*l,**d)
执行结果:完全一致
(11, 22, 3, 4, 55) <class 'tuple'>
{'n1': 23, 'n2': 123} <class 'dict'>
(11, 22, 3, 4, 55) <class 'tuple'>
{'n1': 23, 'n2': 123} <class 'dict'>
字符串格式化format使用这个方式
s1 = '{0} is {1}'
l = ['alex','sb']
#result = s1.format('alex','sb')
result = s1.format(*l)
print(result)
s2 = '{name} is {actor}'
d = {'name':'alex','actor':'sb'}
#result = s2.format(name='alex',actor='sb')
result = s2.format(**d)
print(result)
2、匿名函数
简单函数,只用一行来表示。也叫lambda表达式,lambda存在意义就是对简单函数的简洁表示
#lambda 表达式
func = lambda a:a+1
# 创建形式参数:a
# 函数内容:a+1 返回结果a+1
ret = func(999)
print(ret)
执行结果:
1000
3、内置函数
随便说几个。。。
abs() #绝对值
dict() #字典
help() #帮助
min() #求最小值
setattr()
all() #循环列表,如果列表中所有值均为真,返回真
dir() #查看类方法
hex() #16进制
next()
slice() #切片
any() #循环列表,如果列表中只要有一个真,返回真
divmod() #地板除
id() #查看内存地址
object()
sorted() #排序
ascii() #ascii(9)等价于 int.__repr__(9),并得到返回值
enumerate() #给序列增加一个序号,额外增加一列
input() #输入,等价于python2.x中raw_input
oct() #八进制
staticmethod() #静态方法
bin() #返回二进制数
eval() #将字符串用表达式执行,返回结果eval('6*8')->48
int() #转化为int类型
open() #打开文件
str() #转化为字符串类型
bool() #返回bool值
exec()
isinstance() #判断类型的方法
sum() #求和
bytearray() #返回字节数组
filter() #过滤部分成员
issubclass()
pow() #幂
super() #父类
bytes() #返回字节
float() #转化为浮点数
iter()
print() #打印
tuple() #转化为元组
callable() #是否可执行,能够被调用返回True,即类中有__call__方法
format()
len() #求长度
property()
type() #类型
chr() #ascii码数字转化为字符
ord() #字符转化为ascii码数字
frozenset() #不能增加和修改的集合
list() #转化为列表
range() #拿到数的区间,等同于python2.x的xrange()
vars() #返回dir()中对应的值
classmethod() #类方法
getattr()
locals() #局部变量
repr() #调用__repr__
zip() #
compile() #编译。。。
globals() #返回当前所有可用的变量
map() #针对每个成员执行
reversed() #翻转
__import__()
complex() #复数
hasattr()
max() #求最大值
round() #四舍五入
delattr()
hash() #哈希,如果字典中的字符串太大,通过hash来计算下,节约内存空间
memoryview()
set() #集合
li = ['a','b','c']
for i,item in enumerate(li,1):
print(i,item)
执行结果:
1 a
2 b
3 c
>>> all(['1','s',1,2,''])
False
>>> any([[],(),{},'',0,1])
True
4、open函数
open函数是打开文件的重要函数。
f = open('text.txt', 'r', encoding='utf-8')
ret = f.read(4) #安装字符来读的,python3.x
ret2 = f.tell() #按照字节来获取指针位置
f.close()
print(ret)
print(ret2)
f = open('text.txt', 'r', encoding='utf-8')
f.seek(3) #跳到指针位置,如果是1或者2的话会报错(一个汉字三个字节)
ret = f.read()
f.close()
print(ret)
f = open('text.txt', 'r+', encoding='utf-8')
f.seek(3)
f.truncate() #删除指针后面的所有字符,然后保存到文件中
f.close()
执行结果:
二asd
6
asdasdasdasdasdasd
五、作业:修改配置文件
1、用户输入字符串
‘{"backend": "test.oldboy.org","record":{"server": "100.1.7.999","weight": 20,"maxconn": 30}}’
2、将用户输入的字符串转换为字典
s = input('input your text:')
import json
dic = json.loads(s)
3、添加到行后面
4、删除【可选】
5、不存在如何???【可选】