python之路-基础篇-第三周

一、集合: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、不存在如何???【可选】

http://www.cnblogs.com/wupeiqi/articles/4950799.html

posted @ 2016-01-19 21:20  felo  阅读(436)  评论(0编辑  收藏  举报