这一篇博文是【 AI学习路线图】系列文章的其中一篇,点击查看目录:AI学习完整路线图
这个博文的内容都是基于Python3.6.2版本,由于Python3和Python3有很多不同,所以这个笔记中的代码可能在Python2下会无法运行。
Python是一种解释型、面向对象、动态数据类型的高级程序设计语言,是由Guido van Rossum于1989年底发明的。
(1) 标准数据类型
Python中有6个标准的数据类型:
if __name__ == '__main__':
s = 1
print(type(s))
s = 'a'
print(type(s))
输出:
<class 'int'>
<class 'str'>
也可以用isinstance判断类型:
if __name__ == '__main__':
s = 1
print(isinstance(s,int))
s = 'a'
print(isinstance(s,str))
输出:
True
True
type和isinstance的区别是ininstance认为子类是一种父类类型,type认为不相同。
(1) 算术运算符
假设变量a为10,b为21
运算符 | 描述 | 实例 |
---|---|---|
+ | 加 - 两个对象相加 | a + b 输出结果 31 |
- | 减 - 得到负数或是一个数减去另一个数 | a - b 输出结果 -11 |
* | 乘 - 两个数相乘或是返回一个被重复若干次的字符串 | a * b 输出结果 210 |
/ | 除 - x 除以 y | b / a 输出结果 2.1 |
% | 取模 - 返回除法的余数 | b % a 输出结果 1 |
** | 幂 - 返回x的y次幂 | a**b 为10的21次方 |
// | 取整除 - 返回商的整数部分 | 9//2 输出结果 4 , 9.0//2.0 输出结果 4.0 |
(2) 比较运算符
假设变量a为10,b为21
运算符 | 描述 | 实例 |
---|---|---|
== | 等于 - 比较对象是否相等 | (a == b) 返回 False。 |
!= | 不等于 - 比较两个对象是否不相等 | (a != b) 返回 True。 |
> | 大于 - 返回x是否大于y | (a > b) 返回 False。 |
< | 小于 - 返回x是否小于y。所有比较运算符返回1表示真,返回0表示假。这分别与特殊的变量True和False等价。注意,这些变量名的大写。 | (a < b) 返回 True。 |
= |
大于等于 - 返回x是否大于等于y。 | (a >= b) 返回 False。 |
<= | 小于等于 - 返回x是否小于等于y。 | (a <= b) 返回 True。 |
(3) 赋值运算符
假设变量a为10,b为21
运算符 | 描述 | 实例 |
---|---|---|
= | 简单的赋值运算符 | c = a + b 将 a + b 的运算结果赋值为 c |
+= | 加法赋值运算符 | c += a 等效于 c = c + a |
-= | 减法赋值运算符 | c -= a 等效于 c = c - a |
*= | 乘法赋值运算符 | c *= a 等效于 c = c * a |
/= | 除法赋值运算符 | c /= a 等效于 c = c / a |
%= | 取模赋值运算符 | c %= a 等效于 c = c % a |
**= | 幂赋值运算符 | c **= a 等效于 c = c ** a |
//= | 取整除赋值运算符 | c //= a 等效于 c = c // a |
(4) 逻辑运算符
假设变量a为10,b为21
运算符 | 逻辑表达式 | 描述 | 实例 |
---|---|---|---|
and | x and y | 布尔”与” - 如果 x 为 False,x and y 返回 False,否则它返回 y 的计算值。 | (a and b) 返回 20。 |
or | x or y | 布尔”或” - 如果 x 是 True,它返回 x 的值,否则它返回 y 的计算值。 | (a or b) 返回 10。 |
not | not x | 布尔”非” - 如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。 | not(a and b) 返回 False |
(5) 位运算符
变量 a 为 60,b 为 13二进制格式如下
a = 0011 1100
b = 0000 1101
运算符 | 描述 | 实例 |
---|---|---|
& | 按位与运算符:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0 | (a & b) 输出结果 12 ,二进制解释: 0000 1100 |
按位或运算符:只要对应的二个二进位有一个为1时,结果位就为1。 | ||
^ | 按位异或运算符:当两对应的二进位相异时,结果为1 | (a ^ b) 输出结果 49 ,二进制解释: 0011 0001 |
~ | 按位取反运算符:对数据的每个二进制位取反,即把1变为0,把0变为1。 ~x 类似于 -x-1 | (~a ) 输出结果 -61 ,二进制解释: 1100 0011, 在一个有符号二进制数的补码形式。 |
<< | 左移动运算符:运算数的各二进位全部左移若干位,由”<<”右边的数指定移动的位数,高位丢弃,低位补0。 | a << 2 输出结果 240 ,二进制解释: 1111 0000 |
> |
右移动运算符:把”>>”左边的运算数的各二进位全部右移若干位,”>>”右边的数指定移动的位数 | a >> 2 输出结果 15 ,二进制解释: 0000 1111 |
(6) 成员运算符
运算符 | 描述 | 实例 |
---|---|---|
in | 如果在指定的序列中找到值返回 True,否则返回 False。 | x 在 y 序列中 , 如果 x 在 y 序列中返回 True。 |
not in | 如果在指定的序列中没有找到值返回 True,否则返回 False。 | x 不在 y 序列中 , 如果 x 不在 y 序列中返回 True。 |
(7) 身份运算符
运算符 | 描述 | 实例 |
---|---|---|
is | is 是判断两个标识符是不是引用自一个对象 | x is y , 类似 id(x) == id(y) , 如果引用的是同一个对象则返回 True,否则返回 False |
is not | is not 是判断两个标识符是不是引用自不同对象 | x is not y , 类似 id(a) != id(b)。如果引用的不是同一个对象则返回结果 True,否则返回 False。 |
(8) 运算符优先级
优先级由高到低为:
运算符 | 描述 |
---|---|
** | 指数 (最高优先级) |
~ + - | 按位翻转, 一元加号和减号 (最后两个的方法名为 +@ 和 -@) |
* / % // | 乘,除,取模和取整除 |
|
加法减法 |
<< |
右移,左移运算符 |
& | 位 ‘AND’ |
^ | |
<= < > >= | 比较运算符 |
<> == != | 等于运算符 |
= %= /= //= -= += *= **= | 赋值运算符 |
is is not | 身份运算符 |
in not in | 成员运算符 |
not or and | 逻辑运算符 |
(1) if语句
简单的if:
list = [2, 5, 1, 9, 3, 7, 11, 14, 18]
for item in list:
if item > 5:
print(str(item) + " 大于5")
if – else:
list = [2, 5, 1, 9, 3, 7, 11, 14, 18]
for item in list:
if item > 5:
print(str(item) + " 大于5")
else:
print(str(item) + " 不大于5")
if-elif-else:
list = [2, 5, 1, 9, 3, 7, 11, 14, 18]
for item in list:
if item > 10:
print(str(item) + " 大于10")
elif item > 5:
print(str(item) + " 大于5")
else:
print(str(item) + " 不大于5")
(2) 是否相等/不等
list = [2, 5, 1, 9, 3, 5, 7, 11, 14, 18]
for item in list:
if item == 5:
print("第" + str(list.index(item)) + "个是5")
elif item != 3:
print("第" + str(list.index(item)) + "不是3")
(3) 多个条件 and/or
list = [2, 5, 1, 9, 3, 5, 7, 11, 14, 18]
for item in list:
if item > 5 and item < 10:
print(item)
list = [2, 5, 1, 9, 3, 5, 7, 11, 14, 18]
for item in list:
if item < 5 or item > 10:
print(item)
(4) 是否包含/不包含在列表中
list = [2, 5, 1, 9, 3, 5, 7, 11, 14, 18]
if 4 in list:
print("4包含在列表中")
else:
print("no 4")
list = [2, 5, 1, 9, 3, 5, 7, 11, 14, 18]
if 4 not in list:
print("no 4")
(5) 确定列表是否为空
list = [2, 5, 1, 9, 3, 7, 11, 14, 18]
if list:
for item in list:
print(item)
(1) 使用while
s=0
n=1;
while n<=10:
s=s+n
n=n+1
print(s)
(2) for循环
if __name__ == '__main__':
for i in range(1,9):
print(i)
list=['a',4,"g",True]
for i in list:
print(i)
(3) break
# 如果平方大于100就退出
for item in range(1, 100):
if (item ** 2 > 100):
break
else:
print(item)
print("=======================")
(4) continue
# 如果是偶数就进入下一个循环
for item in range(1, 10):
if (item ** 2 % 2 == 0):
continue
else:
print(item)
(1) 定义函数
def hello(name, msg):
'''打印信息'''
print(name, ',', msg)
def表明要定义一个函数,hello是函数名称,name和msg是两个形参,三个单引号引起来的内容是这个函数的说明,用于生成说明文档。函数体是一句话用打印内容。
(2) 关键字实参
def hello(name, msg):
'''打印信息'''
print(name, ',', msg)
if __name__ == "__main__":
#顺序实参,是根据参数顺序赋值给函数形参
hello("chybin", "hello")
#关键字实参是指定形参的关键字,所以顺序就无所谓了
hello(msg="hello!", name="chybin")
(3) 函数形参指定默认值
def hello(name, msg='你好'):
'''打印信息'''
print(name, ',', msg)
if __name__ == "__main__":
hello("chybin")
hello("chybin","hello")
指定了msg的默认值,当调用函数时,可以不传msg参数,就是用定义的默认值,如果指定了参数,就使用指定的参数。
(4) 返回字典
当函数的返回值有多个时,可以封装为一个字典返回。
(5) 不定长参数
def mylist(*list):
r = []
for item in list:
r.append(item * 2)
return r
if __name__ == "__main__":
r = mylist(4, 6, 2, 9, 10)
print(r)
r = mylist(55,66)
print(r)
参数前面有个*,表明参数个数不确定,就是定一个一list的列表,接收传递的参数。
(6) 不定长的关键字参数
def userinfo(name, age, **otherInfo):
info = {}
info['name'] = name
info['age'] = age
for key, val in otherInfo.items():
info[key] = val
print(info)
if __name__ == '__main__':
userinfo('jock', 20, province='河北', city='廊坊')
(7) 函数嵌套
# 函数嵌套
def fun1():
def fun2():
print("function2")
print("fun1")
return fun2
if __name__ == '__main__':
obj = fun1()
print('-------')
obj()
函数中可以再定义函数,外层函数可以将内层函数做为一个返回值返回,调用方可以对返回的函数进行执行操作。
(8) 函数闭包
# 函数闭包
def f0(x):
def f1(y):
print(x + y)
return f1
if __name__ == '__main__':
obj = f0(10)
obj(20)
(9) 装饰器
# 定义一个装饰器方法,log可以装饰其他方法
def log(func):
# 定义一个内部方法,将这个方法做为装饰器的返回值,装饰后会执行它
def wrap(*args, **kwargs):
# 装饰器内做的工作
print("添加日志开始")
# 其中一项工作是执行被装饰的方法
r = func(*args, **kwargs)
print("添加日志结束")
# 将被装饰的方法返回值返回装饰器
return r
return wrap
# 用@来表示装饰器,加载被装饰方法的头上
@log
def delete(name):
print("删除" + name + "操作")
return "ok"
if __name__ == '__main__':
#执行被装饰的方法时,会先执行装饰器,由装饰器来执行delete方法。
r = delete("jock")
print(r)
带参数的装饰器:
# 定义一个装饰器方法,log2可以装饰其他方法
def log2(i):
def wrap1(func):
# 定义一个内部方法,将这个方法做为装饰器的返回值,装饰后会执行它
def wrap(*args, **kwargs):
# 装饰器内做的工作
print("添加日志开始")
# 其中一项工作是执行被装饰的方法
r = func(*args, **kwargs)
print("添加日志结束")
print(i)
# 将被装饰的方法返回值返回装饰器
return r
return wrap
return wrap1
# 用@来表示装饰器,加载被装饰方法的头上
@log2(10)
def delete(name):
print("删除" + name + "操作")
return "ok"
if __name__ == '__main__':
# 执行被装饰的方法时,会先执行装饰器,由装饰器来执行delete方法。
r = delete("jock")
print(r)
(10) 迭代器
import itertools
a = [1, 2, 3]
b = ['a', 'b', 'c']
x = range(1, 5)
com1 = itertools.combinations(x, 3) # 排列
com2 = itertools.permutations(x, 3) # 组合
com3 = itertools.product(a, b) # 笛卡尔积
com4 = itertools.chain(com1, com2, com3) # 链接
print("-----com1-----")
for i in com1:
print(i)
com1 = itertools.combinations(x, 3) # 排列
print("---com2----")
for i in com2:
print(i)
print("--com3------")
for i in com3:
print(i)
print("====com4======")
for m in com4:
print(m)
对上述代码的猜测:
iteertools生成的对象只能被迭代一次,所以第二次对com1、com2、com3迭代就会发现打印为空。
另外chain链接是对com1、com2、com3的引用的链接,前面对com1进行迭代过后,com4所对应的引用也为空了。
有一定顺序排列的元素组成列表,可将任何东西都放入列表中,用[]来表示列表。
mylist=[1,'a',False,9.8]
print(mylist)
mylist=[1,'a',False,9.8]
print(mylist[0])
print(mylist[1])
print(mylist[2])
print(mylist[3])
mylist=[1,'a',False,9.8]
mylist[0]='b'
print(mylist)
输出:
['b', 'a', False, 9.8]
mylist=[1,'a',False,9.8]
mylist.append(0)
print(mylist)
输出:
[1, 'a', False, 9.8, 0]
mylist=[1,'a',False,9.8]
mylist.insert(1,'88')
print(mylist)
输出:
[1, '88', 'a', False, 9.8]
mylist=[1,'a',False,9.8]
del mylist[3]
print(mylist)
输出:
[1, 'a', False]
mylist=[1,'a',False,9.8]
f=mylist.pop(0)
print(mylist)
print(f)
mylist.pop()
print(mylist)
mylist.pop()
print(mylist)
输出:
['a', False, 9.8]
['a', False]
['a']
弹出元素是将最后一个或者指定位置的元素删除,删除后还可以得到被删除的元素。
mylist=[1,'a',False,'a',9.8]
mylist.remove('a')
print(mylist)
输出:
[1, False, 'a', 9.8]
根据值删除元素只能删除第一个元素。
mylist=[9,4,1,8,2]
mylist.sort()
print(mylist)
输出:
[1, 2, 4, 8, 9]
mylist=[9,4,1,8,2]
mylist.sort(reverse=True)
print(mylist)
输出:
[9, 8, 4, 2, 1]
永久排序后原来的列表顺序就变了。
mylist = [9, 4, 1, 8, 2]
print(sorted(mylist))
print(mylist)
输出:
[1, 2, 4, 8, 9]
[9, 4, 1, 8, 2]
临时排序没有修改原列表的顺序。
mylist = [9, 4, 1, 8, 2]
mylist.reverse();
print(mylist)
输出:
[2, 8, 1, 4, 9]
反转列表是将原列表修改
mylist = [9, 4, 1, 8, 2]
print(len(mylist))
输出:
5
mylist = [9, 4, 1, 8, 2]
for item in mylist:
print(item)
输出:
9
4
1
8
2
mylist = [9, 4, 1, 8, 2]
print(min(mylist))
print(max(mylist))
print(sum(mylist))
输出:
1
9
24
result=[val*2 for val in range(1,9)]
print(result)
输出:
[2, 4, 6, 8, 10, 12, 14, 16]
列表解析是对于列表进行逐个计算,得到另外一个列表的过程,
mylist = [9, 4, 1, 8, 2]
print(mylist[1:3])
print(mylist)
输出:
[4, 1]
[9, 4, 1, 8, 2]
切片是将列表中的一部分切出来,要指定开始的索引值和结束的索引值,但是切片不包含结束索引,类似range(1,9),不包括9。
切片是将原列表中一部分切出来,复制到一个新的空间,所以对切片的修改不会影响到原列表。
几种常见的表达:
mylist = [9, 4, 1, 8, 2]
# 指定开始,不指定结束,就是从开始切到最后,包括开始索引值
# 结果为[1, 8, 2]
print(mylist[2:])
# 不指定开始,从开始切到指定索引值,不包括结束
# 结果为[9, 4]
print(mylist[:2])
# 不指定开始和结束,就是全部切下来
# 结果为[9, 4, 1, 8, 2]
print(mylist[:])
# 指定步长,索引值能被步长值整除的保留下来
# 结果:[9, 1, 2]
print(mylist[::2])
# 结束为负数,最后一个为-1,
# #也可以理解为从后面切下去几个
# 结果[9, 4, 1, 8]
print(mylist[:-1])
# 结束为负数,倒数第二个为-2,
# 结果[9, 4, 1]
print(mylist[:-2])
# 开始为负数,从倒数第几个切
# 结果:[1, 8, 2]
print(mylist[-3:])
不能通过=赋值的方式复制列表,因为=只是修改复制了对列表的索引,并没有复制值,修改了新的列表,老的列表也会修改。例如:
mylist = [9, 4, 1, 8, 2]
print(mylist)
mylist2 = mylist
mylist2.pop()
print(mylist)
输出:
[9, 4, 1, 8, 2]
[9, 4, 1, 8]
可以通过就列表的全部切片进行复制
mylist = [9, 4, 1, 8, 2]
print(mylist)
mylist2 = mylist[:]
mylist2.pop()
print(mylist)
输出:
[9, 4, 1, 8, 2]
[9, 4, 1, 8, 2]
mylist = [9, 4, 1, 8, 2]
if 4 in mylist:
print("exist")
else:
print("no")
if 4 not in mylist:
print("yes")
else:
print("no")
输出:
exist
不可变的列表就是元组。
my_tup=(1,2,'3')
定义元组和定义列表一样,但是元组是用圆括号标示。
my_tup=(1,2,'3')
for tup in my_tup:
print(tup)
元组的值不可以修改,但是元组变量可以重新赋值进行修改。
my_tup=(1,2,'3')
for tup in my_tup:
print(tup)
my_tup=('a','b',True)
print("修改后:")
for tup in my_tup:
print(tup)
tup = (1, 2, 3, 4, 5)
# 根据索引取值
print(tup[2])
# 根据开始结束索引切片
print(tup[1:4])
# -1就是倒数第一个
print(tup[2:-1])
header 表达式 | 结果 | 描述 |
---|---|---|
len((1,2,3)) | 3 | 元组长度 |
(1,2)+(3,)) | (1,2,3) | 元组连接 |
(‘h’,)*2 | (‘h’,’h’) | 复制元素 |
1 in (1,2) | True | 是否存在 |
Python中字典是一系列的键值对,与键关联的值可以是数字、字符串、列表、字典等任何对象。
dict = {'id': 1, 'name': 'Chybin', 'gril_friend_id': [1, 2, 3]}
定义字典用花括号标示。
dict = {'id': 1, 'name': 'Chybin', 'gril_friend_id': [1, 2, 3]}
print(dict["id"])
print(dict["name"])
字典是一种动态结构,可以随时添加键值对,
dict = {'id': 1, 'name': 'Chybin', 'gril_friend_id': [1, 2, 3]}
dict["x"]=123
dict["y"]="abc"
print(dict)
dict = {'id': 1, 'name': 'Chybin', 'gril_friend_id': [1, 2, 3]}
dict["id"]=99
print(dict)
dict = {'id': 1, 'name': 'Chybin', 'gril_friend_id': [1, 2, 3]}
del dict['name']
print(dict)
dict = {'id': 1, 'name': 'Chybin', 'gril_friend_id': [1, 2, 3]}
for k, v in dict.items():
print("key=" + k + ";value=" + str(v))
dict = {'id': 1, 'name': 'Chybin', 'gril_friend_id': [1, 2, 3]}
for k in dict.keys():
print(k)
dict = {'id': 1, 'name': 'Chybin', 'gril_friend_id': [1, 2, 3]}
for k in sorted(dict.keys()):
print(k + ":" + str(dict[k]))
通过sorted对key进行排序
dict = {'id': 1, 'name': 'Chybin', 'gril_friend_id': [1, 2, 3]}
for v in dict.values():
print(v)
list=[]
dict = {'id': 1, 'name': 'Chybin', 'gril_friend_id': [1, 2, 3]}
for i in range(1,6):
list.append(dict)
print(list)
集合是无序不重复的列表
Python中模块是一个python文件,以.py结尾。把相关的代码放入一个模块中,使得程序更加清晰。模块中能定义函数、类、变量等。
定义一个模块,放入文件myprint.py中。
#!/usr/local/bin python3
# coding=utf-8
def printInfo():
print(1)
print(1.0)
print("hello world!")
print(True)
def jiujiu():
i = 1
while i <= 9:
j = 1
while j <= i:
print(str(j) + "*" + str(i) + "=" + str(i * j) + " ", end="")
j = j + 1
print("\r")
i = i + 1
在另外一个py文件中,导入myprint整个模块
import myprint
if __name__ == '__main__':
# 使用模块名.函数名调用方法
myprint.jiujiu()
运行结果如下:
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
from myprint import jiujiu
if __name__ == '__main__':
jiujiu()
这个例子只是导入模块中的一个函数,调用时不用指定模块名,直接使用函数名。
from myprint import *
if __name__ == '__main__':
jiujiu()
这个是将所有的函数都导入到当前模块中,对于其他人的大型模块一定要慎用,因为可能会造成名字冲突。
import myprint as mp
if __name__ == '__main__':
mp.jiujiu()
当模块名字比较长时,可以指定一个别名,之后用别名调用。
Python中有一个multiprocessing模块来实现多进程。
使用Process类来创建进程类。
构造方法为:Process([group [,target [, name [, args [, kwargs]]]])
常用方法有:
is_alive()、join([timeout])、run()、start()。
常用属性有:
daemon、name、pid
实例1:进程为执行函数
#-*-coding:utf-8
import multiprocessing
import time
#创建函数并将其作为单个进程
def worker(interval): #interval间歇,间隔
n = 5 #进程数
while n > 0:
print("The time is {0}".format(time.ctime())) #初始化时间
time.sleep(interval) #睡眠时间
n -= 1 #递减
if __name__ == "__main__":
#创建一个进程,target:调用对象,args:传参数到对象,此处表示睡眠值
p = multiprocessing.Process(target=worker, args=(3,))
p.start() #开启进程
print("p.pid:", p.pid) #进程号
print("p.name:", p.name) #别名
print("p.is_alive:", p.is_alive()) #进程是否存活
实例2: 函数多个进程:
# -*-coding:utf-8
import multiprocessing
import time
# 创建函数并将其作为多个进程
def worker_1(interval):
time.sleep(interval)
print("worker_1")
print("end worker_1")
def worker_2(interval):
time.sleep(interval)
print("worker_2")
print("end worker_2")
def worker_3(interval):
time.sleep(interval)
print("worker_3")
print("end worker_3")
if __name__ == "__main__":
# 定义三个进程对象
p1 = multiprocessing.Process(target=worker_1, args=(2,))
p2 = multiprocessing.Process(target=worker_2, args=(3,))
p3 = multiprocessing.Process(target=worker_3, args=(4,))
# 启动三个进程
p1.start()
p2.start()
p3.start()
# 打印当前CPU逻辑核的数量
print("The number of CPU is:" + str(multiprocessing.cpu_count()))
for p in multiprocessing.active_children():
print("child p.name:" + p.name + "\tp.id" + str(p.pid))
p1.join()
p2.join()
p3.join()
print("END!!!!!!!!!!!!!!!!!")
实例3:指定进程为一个类,继承multiprocessing.Process
#-*-coding:utf-8
import multiprocessing
import time
#将进程定义为类
#定义一个类,一定要继承multiprocessing.Process
class ClockProcess(multiprocessing.Process):
#初始化方法
def __init__(self, interval):
multiprocessing.Process.__init__(self)
self.interval = interval
#进程p调用start()时,自动调用run()
def run(self):
print("----子进程开始")
n = 5
while n > 0:
print("the time is {0}".format(time.ctime()))
time.sleep(self.interval)
n -= 1
if __name__ == '__main__':
print("===主进程开始")
#实例化一个类,这个类继承于multiprocessing.Process
p = ClockProcess(3)
#调用start方法后,就是在子进程中执行了run方法
p.start()
p.join()
print("====主进程结束")
Queue是多进程安全的队列,可以使用Queue实现多进程之间的数据传递。
# -*-coding:utf-8
import multiprocessing
# Queue是多进程安全的队列,可以使用Queue实现多进程之间的数据传递
def writer_proc(q):
try:
# put方法用以插入数据到队列中
q.put(1, block=False)
except:
pass
def reader_proc(q):
try:
# get方法可以从队列读取并且删除一个元素
print(q.get(block=False))
except:
pass
if __name__ == "__main__":
# 定义一个队列,用于进程间的数据传递
q = multiprocessing.Queue()
# 新建一个进程,运行writer_proc方法,将对列传给进程
writer = multiprocessing.Process(target=writer_proc, args=(q,))
writer.start()
# 新建一个进程,运行reader_proc方法,将对列传给进程
reader = multiprocessing.Process(target=reader_proc, args=(q,))
reader.start()
reader.join()
writer.join()
Python中的多线程其实并不是真正的多线程,是单线程利用GIL锁(global interpreter lock 全局解释器锁)模拟实现了的多线程。
Python中多线程模块有thread模块和threading模块,推荐使用threading模块,因为threading模块已经封装了现车的同步问题,使用起来更加方便。
# -*-coding:utf-8
import time
from threading import Thread
# 多线程实现
def loop(name, seconds):
print('子线程开始:', name, ' at:', time.ctime())
time.sleep(seconds)
print('子线程结束:', name, ' at:', time.ctime())
if __name__ == '__main__':
loops = [2, 4]
nloops = range(len(loops))
threads = []
print('主进程开始 :', time.ctime())
for i in nloops:
t = Thread(target=loop, args=(i, loops[i],))
threads.append(t)
for i in nloops:
threads[i].start()
for i in nloops:
threads[i].join()
print('主进程结束 :', time.ctime())
输出:
主进程开始 : Tue Oct 31 07:48:05 2017
子线程开始: 0 at: Tue Oct 31 07:48:05 2017
子线程开始: 1 at: Tue Oct 31 07:48:05 2017
子线程结束: 0 at: Tue Oct 31 07:48:07 2017
子线程结束: 1 at: Tue Oct 31 07:48:09 2017
主进程结束 : Tue Oct 31 07:48:09 2017
#-*-coding:utf-8
import queue
#队列
# 定义一个队里,默认是先入先出
q = queue.Queue()
# 判断是否为空,空返回True
print(q.empty())
q.put("d1")
q.put("d2")
q.put("d3")
# 判断是否满,满返回True
print(q.full())
print(q.get()) # d1
print(q.get()) # d2
print(q.get()) # d3
# 阻塞 可以使用q.get(timeout = 1)设置超时来解决阻塞问题,抛出queue.Empty异常
print(q.get(timeout=1))
# 接上一行的例子,还可以设置不要等待,没有数据即刻抛出异常
print(q.get_nowait())
# 或者使用if判断qsize是否等于0
print(q.qsize())
# block参数False也可以解决程序阻塞问题
print(q.get(block=False))
# 设置具有长度限制的队列
q = queue.Queue(maxsize=3) # 长度为3
q.put(1)
q.put(2)
q.put(3)
# 这里程序又阻塞了,所以可以使用block,timeout参数解决阻塞问题,异常queue.Full
q.put(4, block=False)
# 设置优先级队列,数字小的优先级高
q = queue.PriorityQueue()
q.put((1, "King"))
q.put((-1, "Jeson"))
q.put((10, "Tim"))
q.put((5, "Mike"))
print("后入先出-------")
q = queue.LifoQueue() #设置后入先出队列
q.put(1)
q.put(2)
q.put(3)
print(q.get())
print(q.get())
print(q.get())
(3) 实现的生产者消费者实例
# -*-coding:utf-8
import queue
import threading
import time
# 生产者消费者模型
q = queue.Queue(maxsize=10)
# 生产者,每隔0.5秒就生产一个骨头
def producer(name):
count = 1
while True:
# 生成一个骨头,放入队列
q.put("骨头%s" % count)
print(name, "生产了骨头", count)
count += 1
time.sleep(0.5)
# 消费者,每隔1秒就从队列里拿出一个骨头
def consumer(name):
while True:
print("[%s]取到[%s]并且吃了它..." % (name, q.get()))
time.sleep(1)
# 定义一个生产者线程
p = threading.Thread(target=producer, args=("Tim",))
# 定义两个消费者线程
c1 = threading.Thread(target=consumer, args=("King",))
c2 = threading.Thread(target=consumer, args=("Wang",))
p.start()
c1.start()
c2.start()
(4) 实例:
import threading
import time
lock = threading.Lock()
class MyThread(threading.Thread):
def __init__(self, func, args, name=''):
threading.Thread.__init__(self)
self.name = name
self.func = func
self.args = args
def run(self):
print(self.name, "开始了......")
#调用传递进来的方法
self.func(self.args)
def matter1(music):
for i in range(0, len(music)):
print("第", str(i + 1), "首歌是:", str(music[i]))
time.sleep(2)
print("切换到下一首歌...")
def matter2(number):
lock.acquire()
j = 0
while j <= number:
print("我准备写入第", str(j + 1), "行代码")
j = j + 1
time.sleep(1)
print("写入一行代码")
lock.release()
def matter3(snacks):
lock.acquire()
for k in range(0, len(snacks)):
print("我正在听这歌吃", str(snacks[k]), "零食")
time.sleep(5)
print("吃完一个零食")
lock.release()
if __name__ == '__main__':
music = ["music1", "music2", "music3"]
number = 2
snacks = ["咪咪", "辣条"]
start = time.time()
thing1 = MyThread(matter1, music, "听歌线程")
thing2 = MyThread(matter2, number, "打码线程")
thing3 = MyThread(matter3, snacks, "零食线程")
thing1.start()
thing2.start()
thing3.start()
thing1.join()
thing2.join()
thing3.join()
end = time.time()
print("完成时间", str(end - start))
def readFile():
# with关键字是在文件不再使用后,将文件关闭。
# open是打开指定的文件,as 是将open返回的对象存入变量file_object中
with open('1.txt') as file_object:
contents = file_object.read()
print(contents)
if __name__ == '__main__':
readFile()
def readFile():
# with关键字是在文件不再使用后,将文件关闭。
# open是打开指定的文件,as 是将open返回的对象存入变量file_object中
with open('1.txt') as file_object:
# 逐行读取数据
for line in file_object:
# rstrip是去除末尾的回车符号
print(line.rstrip())
if __name__ == '__main__':
readFile()
def readFile():
# with关键字是在文件不再使用后,将文件关闭。
# open是打开指定的文件,as 是将open返回的对象存入变量file_object中
with open('1.txt') as file_object:
# 将读取的行放入一个列表中
lines = file_object.readlines()
print(lines)
if __name__ == '__main__':
readFile()
def writeFile():
# open是打开指定的文件,w是以写入模式打开文件
with open('2.txt', 'w') as file_object:
for i in range(0, 10):
# write不会写入换行符,如果要换行,可以使用\n
file_object.write(str(i) + "\n")
if __name__ == '__main__':
writeFile()
写入文件也需要先打开文件,第二个参数是指定以什么模式打开文件,w是写入模式,a是追加模式,r是只读模式,r+是可读可写模式。当为w时,如果文件不存在就新建,如果存在就请空文件后写入。
def writeFile():
# open是打开指定的文件,a是以追加模式打开文件
with open('2.txt', 'a') as file_object:
for i in range(10, 20):
# write不会写入换行符,如果要换行,可以使用\n
file_object.write(str(i) + "\n")
if __name__ == '__main__':
writeFile()
import os
os.remove("2.txt")
import os
# 创建一个目录
os.mkdir("bf")
# 删除一个目录
os.rmdir("bf")
# 获取当前目录路径
print(os.getcwd())
# 定义个名为Dog的类
class Dog():
"""小狗类"""
#__init__方法是一个初始化方法,是个特殊的函数,当创建类时会自动执行这个初始化函数。
#前后的下划线是一种约定的格式,目的是区分普通函数。
#self是指当前类的实例。
def __init__(self, name, age):
"""初始化方法"""
self.name = name
self.age = age
#定义了函数,参数self是指当前类的实例,在函数中可以使用当前实例。
def sit(self):
"""小狗蹲下"""
print(self.name.title() + "is sitting")
def roll_over(self):
"""小狗打滚"""
print(self.name.title() + "rolled over")
#根据类的初始化函数创建一个类的实例
my_dog = Dog("jock", 3)
#调用类实例的函数
my_dog.sit()
#使用属性
print(my_dog.name)
class Single():
c = 1
def __setattr__(self, key, value):
self.__dict__[key] = value
pass
def __init__(self, x):
print(x)
def __init__(self):
print("1111")
def add(self, x, y):
print(x + y)
def add(self, x, y, z):
print(x + y + z)
s = Single()
s.add(1, 2)
类都有一个默认的初始化方法init,实例化类时会自动调用这个初始化方法,一个类只能有一个init方法。如果定义了多个,以最后一个为准。
另外Python类里普通的方法也不支持重载,如果有多个相同名称的方法,后面的方法会覆盖前面的方法。
class Person():
def eat(self):
print("吃饭")
# 调用私有方法时,要使用self来调用。
self.__sleep()
# 方法名称前面添加两个下划线,这个方法是就私有方法
# 私有方法不能被类外部调用,只能在本类中调用
def __sleep(self):
print("睡觉")
pass
zs = Person()
zs.eat()
# #外部是不能调用私有方法的
# sz.__sleep()
class Person():
# 共有变量
age = 20
# 私有变量名前面要有两个下划线
__happy = True
def eat(self):
print("吃饭")
# 调用私有方法时,要使用self来调用。
self.__sleep()
# 方法名称前面添加两个下划线,这个方法是就私有方法
# 私有方法不能被类外部调用,只能在本类中调用
def __sleep(self):
# 调用私有变量,需要加self
if self.__happy:
print("不睡觉")
else:
print("睡觉")
pass
zs = Person()
zs.eat()
# #外部是不能调用私有方法的
# sz.__sleep()
print(zs.age)
print(Person.age)
# print(zs.__happy) #外部不能调用私有变量
class Person():
'''类的描述信息'''
# 共有变量
age = 20
# 私有变量名前面要有两个下划线
__happy = True
pass
zs = Person()
# 当前所在模块名称
print(__name__)
# 类的名称
print(Person.__name__)
# 类描述文档
print(Person.__doc__)
# 类所属模块
print(Person.__module__)
# 类所有的父元素组成的元组
print(Person.__bases__)
# 类属性组成的字典(包括变量和方法)
print(Person.__dict__)
# 类对象的类型
print(Person.__class__)
一个类可以继承另外一个类,这两个类分别被称为子类和父类。
# 定义个名为Dog的类
class Dog():
"""小狗类"""
#__init__方法是一个初始化方法,是个特殊的函数,当创建类时会自动执行这个初始化函数。
#前后的下划线是一种约定的格式,目的是区分普通函数。
#self是指当前类的实例。
def __init__(self, name, age):
"""初始化方法"""
self.name = name
self.age = age
#定义了函数,参数self是指当前类的实例,在函数中可以使用当前实例。
def sit(self):
"""小狗蹲下"""
print(self.name.title() + "is sitting")
def roll_over(self):
"""小狗打滚"""
print(self.name.title() + "rolled over")
#定义一个子类,机器狗,继承Dog类
class MachineDog(Dog):
"""机器狗类"""
def __init__(self,name,age):
#调用父类的初始化方法,完成父类的初始化
super().__init__(name,age)
#实例化一个子类
m_dog=MachineDog("mdog",1)
#调用子类继承来的方法
m_dog.sit()
这个例子是定义了一个机器狗类,继承Dog类。子类和父类必须要在一个文件中,切父类要在子类前面。
子类可以继承于多个父类,这就涉及到如果多个父类中有相同名称的方法时,调用哪个方法,Python遵循从左到右,深度优先的原则。
class AA:
def a(self):
print("a")
class BB:
def a(self):
print("cc")
class CC(AA, BB):
pass
c = CC()
c.a()
输出为:
a
可以在另外一个py文件中导入类。
from dog import Dog,MachineDog
if __name__ == '__main__':
#根据类的初始化函数创建一个类的实例
my_dog = Dog("jock", 3)
#调用类实例的函数
my_dog.sit()
#使用属性
print(my_dog.name)
#实例化一个子类
m_dog=MachineDog("mdog",1)
#调用子类继承来的方法
m_dog.sit()
if __name__ == "__main__":
try:
print(3 / 0)
except ZeroDivisionError:
print("不能除以0")
if __name__ == "__main__":
try:
print(3 / 0)
except ZeroDivisionError as e:
print("不能除以0", e)
if __name__ == "__main__":
number = int(input("请输入数字:\n"))
try:
n = 80 / number
except ZeroDivisionError:
print("不能除以0")
else:
print("结果为:" + str(n))
#自定义了一个异常类,要继承Exception类
class NotFondNameException(Exception):
def __init__(self):
print("没有发现名称异常初始化了")
pass
def test(name):
if name == "0":
#抛出指定异常
raise NotFondNameException
try:
test("0")
except NotFondNameException as e:
print("截获了异常:")
finally:
print("不管是否异常,都会这行这里!")