python 文档

[TOC]

这个是基于莫凡python,廖雪峰的自学整理

安装

安装python3

1
brew install python3

选择python3 —version
atom 安装 script
cmd shift +p 查找 run 快捷键cmd i
打开setting:cmd + ,
1
pip3 install jupyter

这边用conda更方便

基础功能

Print 功能:

  1. Print(1) 3.5以上一定要有括号
  2. Print string的话 用单引号或者双引号,双引号里面加单引号
  3. \是系统识别符号,数字不可以加字符串

坚持使用4个空格的缩进
大小写敏感的
平方是2**2,2**3三次方,
8%3是取余数,
9//4取整

1
2
3
print(int('2')+3) #int为定义整数型
print(int(1.9)) #当int一个浮点型数时,int会保留整数部分
print(float('1.2')+3) #float()是浮点型,可以把字符串转换成小数

格式化

用%实现

  1. %s表示用字符串替换
  2. %d表示用整数替换
  3. 有几个%?占位符,后面就跟几个变量或者值,顺序要对应好。如果只有一个%?,括号可以省略。
  4. %s永远起作用
    %s 字符串 (采用str()的显示)
    %r 字符串 (采用repr()的显示)
    %c 单个字符
    %b 二进制整数
    %d 十进制整数
    %i 十进制整数
    %o 八进制整数
    %x 十六进制整数
    %e 指数 (基底写为e)
    %E 指数 (基底写为E)
    %f 浮点数
    %F 浮点数,与上相同%g 指数(e)或浮点数 (根据显示长度)
    %G 指数(E)或浮点数 (根据显示长度)
    %% 字符”%”
    1
    2
    3
    print ('Hi, %s, you have $%d.' % ('Michael', 1000000))
    print( 'growth rate: %d %%' % 7)
    print( 'Age: %s. Gender: %s' % (25, True))

定义变量

1
2
3
apple=1
apple_2016='iphone 7 plus'
a,b,c=1,2,3 #定义多个自变量

循环

条件判断

注意不要少写了冒号:

1
2
3
4
5
6
7
age = 3
if age >= 18:
print('adult')
elif age >= 6:
print('teenager')
else:
print(‘kid')

// d82f37493cc3f66494b326395c054980.png //

while循环

循环是while循环,只要条件满足,就不断循环,条件不满足时退出循环。
如果要提前结束循环,可以用break语句

1
2
3
4
5
6
7
n = 1
while n <= 100:
if n > 10: # 当n = 11时,条件满足,执行break语句
break # break语句会结束当前循环
print(n)
n = n + 1
print('END')

continue和break,pass

1
2
3
4
5
6
n = 0
while n < 10:
n = n + 1
if n % 2 == 0: # 如果n是偶数,执行continue语句
continue # continue语句会直接继续下一轮循环,后续的print()语句不会执行
print(n)

for循环

for…in…循环作为迭代器,cmd+[改变tab缩进结构
依次把list或tuple中的每个元素迭代出来,迭代器的作用,
看例子:

1
2
3
names = ['Michael', 'Bob', 'Tracy']
for name in names:
print(name)

range是自定义函数,range(1,10)其实是1-9
1
2
3
4
sum = 0
for x in range(101): # 到100
sum = sum + x
print(sum)

if判断

python 语言中等号的判断使用 == 而不是 =, 因为后一种是赋值语句
要有冒号,<,>.<=,<=,==(等于),!=(不等于),

1
2
3
4
5
x = 1
y = 2
z = 3
if x < y:
print('x is less than y')

if…else…

同等关系,都有冒号

1
2
3
4
if condition:
true_expressions
else:
false_expressions

1
2
3
4
5
6
7
x = 1
y = 2
z = 3
if x > y:
print('x is greater than y')
else:
print('x is less or equal to y')

if..elif…else

1
2
3
4
5
6
7
8
9
10
if condition1:
true1_expressions
elif condition2:
true2_expressions
elif condtion3:
true3_expressions
elif ...
...
else:
else_expressions
1
2
3
4
5
6
7
8
9
10
x = 4
y = 2
z = 3
if x > 1:
print ('x > 1')
elif x < 1:
print('x < 1')
else:
print('x = 1')
print('finish')

定义功能

定义函数

四个空格

1
2
def function_name(parameters):
expressions

函数参数

1
2
3
def fun1(a,b):
c=a*b
print('the c is ',c)

函数的默认参数
没有的放前面,后面有默认的放后面,这样就可以直接输出了

1
2
3
4
5
def sale_car(price, color='red', brand='carmy', is_second_hand=True):
print('price', price,
'color', color,
'brand', brand,
'is_second_hand', is_second_hand,)

可变参数(可变参数在函数定义不能出现在特定参数和默认参数前面)和关键词参数(参数在函数内部自动封装成一个字典(dict))
1
universal_func(*args, **kw)

定义变量

局部变量 和 全局变量
全局通常全部大写,局部变量小写在函数内;如果在方程中

1
2
3
a=None
def fun()
global a=30

模块安装

用别人好的外部模块加载,比如numpy

1
2
3
pip install numpy   # 这是 python2+ 版本的用法
pip3 install numpy # 这是 python3+ 版本的用法
pip3 install -U numpy # 这是 python3+ 版本的用法

文件读写

  1. 就是存模块、文件,下一次再用;
    \n 是换行命令,\t 对齐

    1
    2
    text='This is my first test.\n\tThis is the second line.\n\tThis the third line'
    print(text) # 输入换行命令\n,要注意斜杆的方向。

    open读文件方式
    使用 open 能够打开一个文件, open 的第一个参数为文件名和路径 ‘my file.txt’, 第二个参数为将要以什么方式打开它, 比如 w 为可写方式. 如果计算机没有找到 ‘my file.txt’ 这个文件, w 方式能够创建一个新的文件, 并命名为 my file.txt

    1
    2
    3
    my_file=open('my file.txt','w')   #用法: open('文件名','形式'), 其中形式有'w':write;'r':read.
    my_file.write(text) #该语句会写入先前定义好的 text
    my_file.close() #关闭文件

    打开文件要close

  2. 给文件添加内容
    写文件是用,’w’;追加用’a’

    1
    2
    3
    4
    append_text='\nThis is appended file.'  # 为这行文字提前空行 "\n"
    my_file=open('my file.txt','a') # 'a'=append 以增加内容的形式打开
    my_file.write(append_text)
    my_file.close()
  3. 读文件,是 r
    使用 file.read() 能够读取到文本的所有内容.

    1
    2
    3
    file= open('my file.txt','r') 
    content=file.read()
    print(content)

    按行读取 file.readline(),readlines就是多行输出

    1
    2
    3
    4
    5
    file= open('my file.txt','r') 
    content=file.readline() # 读取第一行
    second_read_time=file.readline() # 读取第二行
    print(content)
    print(second_read_time)

类 Class

  1. 建议首字母大写
  2. 冒号不能缺失
  3. 运行时class要加()
  4. def第一个参数要是self
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Calculator:       #首字母要大写,冒号不能缺
    name='Good Calculator' #该行为class的属性
    price=18
    def add(self,x,y):
    print(self.name)
    result = x + y
    print(result)
    def minus(self,x,y):
    result=x-y
    print(result)
    def times(self,x,y):
    print(x*y)
    def divide(self,x,y):
    print(x/y)
    运行:

    cal=Calculator()
    cal.add(10,20)

class的init功能

其实 __init__可以理解成初始化class的变量,取自英文中initial 最初的意思.可以在运行时,给初始值附值

  1. 还是要有self,必须要有参数,不论是先输入的还是默认的
1
2
3
4
5
6
7
8
9
class Calculator:
name='good calculator'
price=18
def __init__(self,name,price,hight=10,width=14,weight=16): #后面三个属性设置默认值,查看运行
self.name=name
self.price=price
self.h=hight
self.wi=width
self.we=weight

input模块

variable=input() 表示运行后,可以在屏幕中输入一个数字,该数字会赋值给自变量。

1
2
a_input=input('please input a number:')
print('this number is:',a_input)

这儿可以用在if里面,但是在if语句中自变量 a_input 对应的是1 and 2 整数型。输入的内容和判断句中对应的内容格式应该一致。不然返回值是string 所以要是int,或者就是’1’,或者str(1),不然就是int(input(‘plz give a num’))
1
2
3
4
5
6
7
a_input=int(input('please input a number:'))#注意这里要定义一个整数型
if a_input==1:
print('This is a good one')
elif a_input==2:
print('See you next time')
else:
print('Good luck')

元组(tuple) 列表(List)

两个都是有次序的数字
turple 小括号
list 中括号

1
2
3
a_tuple = (12, 3, 5, 15 , 6)
another_tuple = 12, 3, 5, 15 , 6 #tuple
a_list = [12, 3, 67, 7, 82] #list

用作迭代,或者定位 参加for..in..循环
依次输出a_tuple和a_list中的各个元素,这儿的range,还是迭代器,是4,从0开始
1
2
for index in range(len(a_list)):
print("index = ", index, ", number in list = ", a_list[index])

List

list的添加方法:XX.append(‘str’),在最后添加一个
​ 指定位置: xx.insert(位置,‘项目’);
​ 删除:xx.remove(元素),会删掉第一个出现的元素,后面会保留
指数[0]:print(a[0]) :打印出a列表的第0位
a[-1]:从最后面开始算起
a[0:3]:从第0位到第2位,0,1,2,等同于[:3],a[3:5]输出3,4;
​ 还有[5:], [-3:],都是前闭后开
a.index(2):第一次出现2(value)的索引
a.count(2):算出value出现的次数
a.sort():函数排序,从小到大并覆盖


1
2
3
4
5
6
7
classmates.append('Adam')
classmates.insert(1, 'Jack') #在第一位添加jack
a = [4,1,2,3,4,1,1,-1]
a.remove(2)
a.sort() # 默认从小到大排序
a.sort(reverse=True) # 从大到小排序
print(a)

tuple和list非常类似,但是tuple一旦初始化就不能修改,“指向不变”.

dictionary 类型

字典没有顺序,字典每一key对应一个value,key可以是int可以str

  1. 赋值
  2. 输出位置
  3. 删除
  4. 储存类型:字典里面再加字典,也可是fun()
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    dic = {'apple':1,'pear':2}
    d={1:'a',2:'b'}
    dic['lan'] = 'python'
    dic['version'] = 2.7

    for key in dic:
    print(key, dic[key])


    a_list = [1,2,3,4,5,6,7,8]
    print(a_list[0]) # 1列表

    d1 = {'apple':1, 'pear':2, 'orange':3}
    print(d1['apple']) # 1字典 输出
    del d1['pear'] #删除
    d1['platform'] = 64 #赋值

    def func():
    return 0

    d4 = {'apple':[1,2,3], 'pear':{1:3, 3:'a'}, 'orange':func}
    print(d4['pear'][3]) # a

set 类型

找不同,不需要value,可以只有key,没有序列
不能传列表+字符串

1
2
3
4
5
6
7
8
9
10
s = set(['python', 'python2', 'python3','python'])
for item in s:
print(item)

char_list = ['a', 'b', 'c', 'c', 'd', 'd', 'd']
sentence = 'Welcome Back to This Tutorial'

print(set(char_list))
print(set(sentence))
print(set(char_list+ list(sentence)))

添加:

1
2
3
4
unique_char = set(char_list)
unique_char.add('x')
# unique_char.add(['y', 'z']) this is wrong,不能加一个list和重复的数字
print(unique_char)

清除一个元素可以用 remove 或者 discard, 而清除全部可以用 clear.

1
2
3
unique_char.remove('x') #这个返回值就是none
unique_char.discard('d')
unique_char.clear()

筛选:.difference .intersection

1
2
3
unique_char = set(char_list)
print(unique_char.difference({'a', 'e', 'i'})) #不同
print(unique_char.intersection({'a', 'e', 'i'}))

Python 共内置了 list、 tuple 、dict 和 set 四种基本集合,每个集合对象都能够迭代。
dist和set名值对
请务必注意,dict内部存放的顺序和key放入的顺序是没有关系的。需要牢记的第一条就是dict的key必须是不可变对象
和list比较,dict有以下几个特点:

  1. 查找和插入的速度极快,不会随着key的增加而变慢;
  2. 需要占用大量的内存,内存浪费多。
    而list相反:
  3. 查找和插入的时间随着元素的增加而增加;
  4. 占用空间小,浪费内存很少。
    set和dict的唯一区别仅在于没有存储对应的value,但是,set的原理和dict一样,所以,同样不可以放入可变对象,因为无法判断两个可变对象是否相等,也就无法保证set内部“不会有重复元素”。字符串、整数等都是不可变的,因此,可以放心地作为key。而list是可变的,就不能作为key

多维列表

numpy 和 pandas来处理
多维,两个括号

1
2
3
4
5
a = [1,2,3,4,5] # 一行五列

multi_dim_a = [[1,2,3],
[2,3,4],
[3,4,5]] # 三行三列

print(multi_dim_a[0][1]) 第0行第1列,就是输出2,都是从0还是索引的

import 一个模块

方法1

1
2
import time
print(time.localtime()) #这样就可以print 当地时间

方法2
1
2
import time as t
print(t.localtime()) # 需要加t.前缀来引出功能

方法三:from time import time,localtime ,只import自己想要的功能.所用功能就是,可以省略模块名。
1
2
3
4
5
from time import time, localtime
print(localtime())
print(time())

from time import *

自己的模块

保存好模块 xx.py,在同一个目录下即可,在Mac系统中,下载的python模块会被存储到外部路径site-packages,同样,我们自己建的模块也可以放到这个路径,最后不会影响到自建模块的调用。(Library-framework-lib-python-….)

1
import balance

其他

try的错误处理

处理错误
输出错误的方法:try: , except … as …:

1
2
3
4
5
6
7
8
9
10
11
12
try:
file=open('eeee.txt','r+') #这边是读取加写入的操作
except Exception as e:
print(e)
response = input('do you want to create a new file:')
if response=='y':
file=open('eeee.txt','w')
else:
pass
else:
file.write('ssss')
file.close()

zip lambda map

zip函数接受任意多个(包括0个和1个)序列作为参数,合并后返回一个tuple列表.需要list,这个是数项合并

1
2
3
4
5
6
a=[1,2,3]
b=[4,5,6]
ab=zip(a,b)
print(list(ab)) #需要加list来可视化这个功能
for i,j in zip(a,b): #包括迭代器功能
print(i/2,j*2)

lambda定义一个简单的函数,实现简化代码的功能,看代码会更好理解。

1
2
3
4
fun= lambda x,y:x+y
x=int(input('x=')) #这里要定义int整数,否则会默认为字符串
y=int(input('y='))
print(fun(x,y))

map
map是把函数和参数绑定在一起。

1
2
3
4
5
6
7
8
9
10
def fun(x,y):
return (x+y)
list(map(fun,[1],[2])) #这边要list这个函数运算
"""
[3]
"""
list(map(fun,[1,2],[3,4]))
"""
[4,6]
"""

copy & deepcopy 浅复制 & 深复制

copy是一个模块
深拷贝:改变一个变量,另一个也改变,他们指针位置一样,内存空间改变。
浅拷贝:第一层列表是完全指定到另外的内存空间,第二层列表旨在在同一个空间,此时第二层可以变,第一层不变。
a=b:内存空间不变。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import copy

a = [1,2,3]
b = a
b[1]=22
print(a)
print(id(a) == id(b)) #True

# deep copy
c = copy.deepcopy(a)
print(id(a) == id(c)) #false
c[1] = 2
print(a) #[1,2,3]
a[1] = 111 #[1,2,3]
print(c)

# shallow copy
a = [1,2,[3,4]]
d = copy.copy(a)
print(id(a) == id(d)) #false 改变,第一层内存改变
print(id(a[2]) == id(d[2])) #true 第二层不变,包括内存

多线程和多进程

threading 和 multiprocessing
多线程 Threading 是一种让程序拥有分身效果. 能同时处理多件事情. 一般的程序只能从上到下一行行执行代码, 不过 多线程 (Threading) 就能打破这种限制. 让你的程序鲜活起来.

我们在多线程 (Threading) 里提到过, 它是有劣势的, GIL 让它没能更有效率的处理一些分摊的任务. 而现在的电脑大部分配备了多核处理器, 多进程 Multiprocessing 能让电脑更有效率的分配任务给每一个处理器, 这种做法解决了多线程的弊端. 也能很好的提升效率.

多线程

添加线程threading

加载thereading模块
几个函数:

  1. threading.active.acount() ,有几个线程
  2. threading.enumerate(),查看所有线程信息
  3. threading.current_thread(),正在运行的线程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

import threading

#def main():
# print(threading.active_count())
# print(threading.enumerate()) # see the thread list
# print(threading.current_thread())

def thread_job(): #定义线程的工作
print('This is a thread of %s' % threading.current_thread())

def main():
thread = threading.Thread(target=thread_job,) #T大写,添加多线程
thread.start() #开始线程
if __name__ == '__main__':
main()
join功能

线程任务还未完成便输出all done。如果要遵循顺序,可以在启动线程后对它调用join

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import threading
import time
def T1_job():
print("T1 start\n")
for i in range(10):
time.sleep(0.1)
print("T1 finish\n")

def T2_job():
print("T2 start\n")
print("T2 finish\n")

thread_1 = threading.Thread(target=T1_job, name='T1')
thread_2 = threading.Thread(target=T2_job, name='T2')
thread_1.start() # 开启T1
thread_2.start() # 开启T2
thread_2.join() # join for T2
thread_1.join() # join for T1
print("all done\n")

储存进程结果Queue

多线程没有结果,将结果保存在Queue中,线程执行完后,从Queue中获取存储的结果

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
import threading
import time
from queue import Queue #定义一个模块,在小写q模块导入大写Q

def job(l,q):
for i in range(len(l)): #这边的l是一个列表,len(l)就是列表的长度,即个数
l[i] = l[i]**2 #列表的值的平方
q.put(l) #多线程调用的函数不能用return返回值

def multithreading():
q = Queue() #q中存放返回值,代替return的返回值
threads = [] #线程列表
data = [[1,2,3],[3,4,5],[4,4,4],[5,5,5]]
for i in range(4): : #定义四个线程
t = threading.Thread(target=job, args=(data[i], q)) #Thread首字母要大写,被调用的job函数没有括号,只是一个索引,参数在后面
t.start() #开始线程
threads.append(t) #把每个线程append到线程列表中
for thread in threads: #分别join四个线程到主线程
thread.join()
results = [] #定义一个空的列表results,将四个线运行后保存在队列中的结果返回给空列表results
for _ in range(4):
results.append(q.get()) #q.get()按顺序从q中拿出一个值
print(results)

if __name__ == '__main__': #if __name__ == '__main__'的意思是:当.py文件被直接运行时,if __name__ == '__main__'之下的代码块将被运行;当.py文件以模块形式被导入时,if __name__ == '__main__'之下的代码块不被运行。
multithreading() #多线程运算函数

GIL不一定有效率

Python 的设计上, 有一个必要的环节, 就是 Global Interpreter Lock (GIL). 这个东西让 Python 还是一次性只能处理一个东西。
这时候用多进程运算会卡。

线程锁

Lock

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
import threading #导入线程标准模块

def job1():
global A, lock #lock的函数
lock.acquire() #开始lock,job2不会接触job1的程序
for i in range(10):
A += 1
print('job1', A)
lock.release() #关闭lock

def job2():
global A, lock
lock.acquire()
for i in range(10):
A += 10
print('job2', A)
lock.release()

if __name__ == '__main__':
lock = threading.Lock() #一个大写一个小写
A = 0
t1 = threading.Thread(target=job1)
t2 = threading.Thread(target=job2)
t1.start()
t2.start()
t1.join()
t2.join()

多进程

添加进程

导入模块

1
2
3
4
5
6
7
8
9
10
11
12
import multiprocessing as mp #导入模块
import threading as td

def job(a,d):
print('aaaaa')

t1 = td.Thread(target=job,args=(1,2)) #job没有括号,有括号就是调用,这儿是引用这个目标罢了
p1 = mp.Process(target=job,args=(1,2))
t1.start()
p1.start()
t1.join()
p1.join()

完整代码:
1
2
3
4
5
6
7
8
9
import multiprocessing as mp

def job(a,d):
print('aaaaa')

if __name__=='__main__': #要在这个函数下面运行,不然报错,同时mac要在terminal下面
p1 = mp.Process(target=job,args=(1,2))
p1.start()
p1.join()

把值储存在queue里面

job本身没有返回值的原因才做这个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import multiprocessing as mp

def job(q):
res = 0
for i in range(1000):
res += i+i**2+i**3
q.put(res) # 放进q里面

if __name__ == '__main__':
q = mp.Queue() # q中存放返回值,代替return的返回值 。这是第一步
p1 = mp.Process(target=job, args=(q,)) #定义两个线程函数,用来处理同一个任务, args 的参数只要一个值的时候,参数后面需要加一个逗号,表示args是可迭代的,后面可能还有别的参数,不加逗号会出错
p2 = mp.Process(target=job, args=(q,))
p1.start()
p2.start()
p1.join()
p2.join()
res1 = q.get()
res2 = q.get()
print(res1+res2)

哪个有效率
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
import multiprocessing as mp
import threading as td
import time

def job(q):
res = 0
for i in range(1000000):
res += i+i**2+i**3
q.put(res) # queue

def multicore():
q = mp.Queue()
p1 = mp.Process(target=job, args=(q,))
p2 = mp.Process(target=job, args=(q,))
p1.start()
p2.start()
p1.join()
p2.join()
res1 = q.get()
res2 = q.get()
print('multicore:' , res1+res2)

def normal():
res = 0
for _ in range(2):
for i in range(1000000):
res += i+i**2+i**3
print('normal:', res)

def multithread():
q = mp.Queue()
t1 = td.Thread(target=job, args=(q,))
t2 = td.Thread(target=job, args=(q,))
t1.start()
t2.start()
t1.join()
t2.join()
res1 = q.get()
res2 = q.get()
print('multithread:', res1+res2)

if __name__ == '__main__':
st = time.time()
normal()
st1= time.time()
print('normal time:', st1 - st)
multithread()
st2 = time.time()
print('multithread time:', st2 - st1)
multicore()
print('multicore time:', time.time()-st2)
进程池
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import multiprocessing as mp

def job(x):
return x*x #pool里面有返回值 ,所以是return

def multicore():
pool = mp.Pool(processes=2) #定义进程池,大写P,这时候有返回值,这是第一步,默认值是所有的核,这边用2个核
res = pool.map(job, range(10))
print(res) # 0.1.4.9....81
res = pool.apply_async(job, (2,)) #apply_async,只给一个值,只在一个核里面运行一次。传入值时要注意是可迭代的,所以在传入值后需要加逗号, 同时需要用get()方法获取返回值
print(res.get()) #结果是4
multi_res =[pool.apply_async(job, (i,)) for i in range(10)] #这边是为了输出很多个值,用迭代器的功能
print([res.get() for res in multi_res]) #结果也在列表中迭代

if __name__ == '__main__':
multicore()

map是Python的内置函数, 使用的方式如下;

list = map(func, iter)
其中, func是函数, iter是可迭代的序列。
它的功能是:将一个序列中的每一个元素应用传入的函数, 并返回一个包含所有函数调用结果的一个列表.

共享内存

共享内存 shared memory,不能多进程分享全局变量

1
2
3
4
5
import multiprocessing as mp

value1 = mp.Value('i', 0) # 形式 , 内容
value2 = mp.Value('d', 3.14)
array = mp.Array('i', [1, 2, 3, 4]) # 整数,一维列表

进程锁

Lock,还是要先定义共享内存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import multiprocessing as mp
import time

def job(v, num):
for _ in range(5):
time.sleep(0.1) # 暂停0.1秒,让输出效果更明显
v.value += num # v.value获取共享变量值
print(v.value, end="")

def multicore():
v = mp.Value('i', 0) # 定义共享变量
p1 = mp.Process(target=job, args=(v,1))
p2 = mp.Process(target=job, args=(v,3)) # 设定不同的number看如何抢夺内存
p1.start()
p2.start()
p1.join()
p2.join()

if __name__ == '__main__':
multicore()

上门会抢夺进程资源,下面是lock
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def job(v, num, l): # 需要将lock传入 第二步
l.acquire() # 锁住 第三步
for _ in range(5):
time.sleep(0.1)
v.value += num # 获取共享内存
print(v.value)
l.release() # 释放

def multicore():
l = mp.Lock() # 定义一个进程锁,第一步
v = mp.Value('i', 0) # 定义共享内存
p1 = mp.Process(target=job, args=(v,1,l)) # 需要将lock传入
p2 = mp.Process(target=job, args=(v,3,l)) #p2 基于p1已经完成的基础上再加3
p1.start()
p2.start()
p1.join()
p2.join()

if __name__ == '__main__':
multicore()

tkinker窗口

一个GUI界面,实现一个直观的窗口

label&button标签和按钮

  1. 导入tkinter模块
  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
    import tkinter as tk

    window = tk.Tk() #对象都是要大写的
    window.title('my window') #名字
    window.geometry('200x100') #大小

    # 这里是窗口的内容
    var = tk.StringVar() # 这时文字变量储存器
    l = tk.Label(window,
    textvariable=var, # 使用 textvariable 替换 text, 因为这个可以变化
    bg='green', font=('Arial', 12), width=15, height=2)
    l.pack() # 固定窗口位置,place()某个点的值

    # 添加按钮
    b = tk.Button(window,
    text='hit me', # 显示在按钮上的文字,还是要大写B
    width=15, height=2,
    command=hit_me) # 点击按钮式执行的命令,就是hit_ne的函数
    b.pack() # 按钮位置

    # 定义hit_me函数
    on_hit = False # 默认初始状态为 False
    def hit_me():
    global on_hit
    if on_hit == False: # 从 False 状态变成 True 状态
    on_hit = True
    var.set('you hit me') # 设置标签的文字为 'you hit me'
    else: # 从 True 状态变成 False 状态
    on_hit = False
    var.set('') # 设置 文字为空

    window.mainloop() #最后一步,不断刷新

输入输出文本框 entry 和 text

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
import tkinter as tk

window = tk.Tk()
window.title('my window')
window.geometry('200x200')

#定义一个输入框
# e = tk.Entry(window, show="*")
e = tk.Entry(window, show="1") #创建输入框entry,用户输入任何内容都显示为*,对象还是要大写
e.pack()

#定义两个按钮的函数
def insert_point():
var = e.get() #获得文本框的值用get()
t.insert('insert', var) #指针所在就是'insert'的形式
def insert_end():
var = e.get()
# t.insert('end', var) 放在尾部就是'end'这个形式
t.insert(2.2, var) #具体地点,某行某列


#定义两个按钮
b1 = tk.Button(window, text='insert point', width=15,
height=2, command=insert_point) #这边两个函数
b1.pack()
b2 = tk.Button(window, text='insert end',
command=insert_end)
b2.pack()

#定义一个文本框
t = tk.Text(window, height=2)
t.pack()

window.mainloop()

Listbox,列表部件

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
import tkinter as tk

#定义一个窗口视图大小
window = tk.Tk()
window.title('my window')
window.geometry('200x200')

#定义label现实,因为是变量
var1 = tk.StringVar()
l = tk.Label(window, bg='yellow', width=4, textvariable=var1)
l.pack()

# 定义光标选中的列表数字传入label的函数
def print_selection():
value = lb.get(lb.curselection()) #得到列表选中的lb值
var1.set(value) #交给var1

#定义button
b1 = tk.Button(window, text='print selection', width=15,
height=2, command=print_selection)
b1.pack()

#定义Listbox
var2 = tk.StringVar() #因为是变量
var2.set((11,22,33,44)) # 定义数据
lb = tk.Listbox(window, listvariable=var2) #定义列表框,列表传入参数
list_items = [1,2,3,4] #列表的index
for item in list_items: #迭代插入lb的数据到位置
lb.insert('end', item)
lb.insert(1, 'first')
lb.insert(2, 'second')
lb.delete(2)
lb.pack()

window.mainloop()

5e513541cd63ad0db10e92d8fe5523b6.png

选择按钮

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
import tkinter as tk

window = tk.Tk()
window.title('my window')
window.geometry('200x200')

var = tk.StringVar()
l = tk.Label(window, bg='yellow', width=20, text='empty')
l.pack()

def print_selection(): #print_selection 功能就是选择了某个 radiobutton 后我们会在屏幕上打印的选项.
l.config(text='you have selected ' + var.get())#config()函数表示里面所有的参数都可以被改变,这个改变了上面text里面的empty

r1 = tk.Radiobutton(window, text='Option A', #装在window里面
variable=var, value='A',#当我们鼠标选中了其中一个选项,把value的值A放到变量var中,然后赋值给variable
command=print_selection)
r1.pack()
r2 = tk.Radiobutton(window, text='Option B',
variable=var, value='B',
command=print_selection)
r2.pack()
r3 = tk.Radiobutton(window, text='Option C',
variable=var, value='C',
command=print_selection)
r3.pack()

window.mainloop()

Scale尺寸

可以拉动,返回的是一个数字
fd2a3b7b3ba091f599014168b7aa18e6.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import tkinter as tk

window = tk.Tk()
window.title('my window')
window.geometry('200x200')

l = tk.Label(window, bg='yellow', width=20, text='empty')
l.pack()

def print_selection(v): #这个有默认的返回值,所以加v
l.config(text='you have selected ' + v)

s = tk.Scale(window, label='try me', from_=5, to=11, orient=tk.HORIZONTAL,
length=200, showvalue=0, tickinterval=2, resolution=0.01, command=print_selection)
s.pack()

window.mainloop()

参数from_=5,to=11的意思就是从5到11,即这个滚动条最小值为5,最大值为11(这里使用from_是因为在python中有from这个关键词)
参数orient=tk.HORIZONTAL在这里就是设置滚动条的方向,如我们所看到的效果图,这里HORIZONTAL就是横向。要加tk
参数length这里是指滚动条部件的长度,但注意的是和其他部件width表示不同,width表示的是以字符为单位,比如width=4,就是4个字符的长度,而此处的length=200,是指我们常用的像素为单位,即长度为200个像素
参数resolution=0.01这里我们可以借助数学题来理解,我们做的很多数学题都会让我们来保留几位小数,此处的0.01就是保留2位小数,
showvalue=0显示的就是效果图,上方无结果显示,如果改为showvalue=1
参数tickinterval设置的就是坐标的间隔,此处为tickinterval=2,

checkbutton 勾选

和radiobutton类似
重点就是参数onvalue和offvalue的值,传入variable里面,同时定义传入的var是IntVar()的函数

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
import tkinter as tk

window = tk.Tk()
window.title('my window')
window.geometry('200x200')

l = tk.Label(window, bg='yellow', width=20, text='empty')
l.pack()

def print_selection():
if (var1.get() == 1) & (var2.get() == 0):
l.config(text='I love only Python ')
elif (var1.get() == 0) & (var2.get() == 1):
l.config(text='I love only C++')
elif (var1.get() == 0) & (var2.get() == 0):
l.config(text='I do not love either')
else:
l.config(text='I love both')

var1 = tk.IntVar()
var2 = tk.IntVar()
c1 = tk.Checkbutton(window, text='Python', variable=var1, onvalue=1, offvalue=0,
command=print_selection)
c2 = tk.Checkbutton(window, text='C++', variable=var2, onvalue=1, offvalue=0,
command=print_selection)
c1.pack()
c2.pack()


window.mainloop()

Canvas 画布

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import tkinter as tk

window = tk.Tk()
window.title('my window')
window.geometry('200x200')

canvas = tk.Canvas(window, bg='blue', height=100, width=200) #加载画布
image_file = tk.PhotoImage(file='ins.gif') #载入图片
image = canvas.create_image(10, 10, anchor='nw', image=image_file) #左上角是铆点
x0, y0, x1, y1= 50, 50, 80, 80
line = canvas.create_line(x0, y0, x1, y1)
oval = canvas.create_oval(x0, y0, x1, y1, fill='red') #创建一个圆,填充色为`red`红色
arc = canvas.create_arc(x0+30, y0+30, x1+30, y1+30, start=0, extent=180) #创建一个扇形
rect = canvas.create_rectangle(100, 30, 100+20, 30+20) #创建一个矩形
canvas.pack()

def moveit(): #canvas.move(rect, 0, 2)的参数(rect,0,2)就是移动rect这个变量,即我们看到的矩形 后面的0和2,也就是横坐标移动0个单位
canvas.move(rect, 0, 2)

b = tk.Button(window, text='move', command=moveit).pack()

window.mainloop()

菜单栏 menubar

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
import tkinter as tk

window = tk.Tk()
window.title('my window')
window.geometry('200x200')

l = tk.Label(window, text='', bg='yellow')
l.pack()
counter = 0
def do_job():
global counter
l.config(text='do '+ str(counter))
counter+=1

##创建一个菜单栏,这里我们可以把他理解成一个容器,在窗口的上方
menubar = tk.Menu(window)
filemenu = tk.Menu(menubar, tearoff=0) ##定义一个空菜单单元
menubar.add_cascade(label='File', menu=filemenu) ##将上面定义的空菜单命名为`File`,放在菜单栏中,就是装入那个容器中

##在`File`中加入`New`的小菜单,即我们平时看到的下拉菜单,每一个小菜单对应命令操作。
##如果点击这些单元, 就会触发`do_job`的功能
filemenu.add_command(label='New', command=do_job)
filemenu.add_command(label='Open', command=do_job)
filemenu.add_command(label='Save', command=do_job)##同样的在`File`中加入`Open`小菜单
filemenu.add_separator() ##这里就是一条分割线
filemenu.add_command(label='Exit', command=window.quit) ##同样的在`File`中加入`Exit`小菜单,此处对应命令为`window.quit`

editmenu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label='Edit', menu=editmenu)
editmenu.add_command(label='Cut', command=do_job)
editmenu.add_command(label='Copy', command=do_job)
editmenu.add_command(label='Paste', command=do_job)

submenu = tk.Menu(filemenu) ##和上面定义菜单一样,不过此处实在`File`上创建一个空的菜单
filemenu.add_cascade(label='Import', menu=submenu, underline=0) ##给放入的菜单`submenu`命名为`Import`
submenu.add_command(label="Submenu1", command=do_job) ##这里和上面也一样,在`Import`中加入一个小菜单命令`Submenu1`

window.config(menu=menubar) #给window改menu属性,这个是特别的地方

window.mainloop()

Frame 框架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import tkinter as tk

window = tk.Tk()
window.title('my window')
window.geometry('200x200')
tk.Label(window, text='on the window').pack() ###定义一个`label`显示`on the window`

###在`window`上创建一个`frame`
frm = tk.Frame(window)
frm.pack()

###在刚刚创建的`frame`上创建两个`frame`,我们可以把它理解成一个大容器里套了一个小容器,即`frm`上有两个`frame` ,`frm_l`和`frm_r`
frm_l = tk.Frame(frm, )
frm_r = tk.Frame(frm)
###这里是控制小的`frm`部件在大的`frm`的相对位置,此处`frm_l`就是在`frm`的左边,`frm_r`在`frm`的右边
frm_l.pack(side='left')
frm_r.pack(side='right')
###这里的三个label就是在我们创建的frame上定义的label部件,还是以容器理解,就是容器上贴了标签,来指明这个是什么,解释这个容器。
tk.Label(frm_l, text='on the frm_l1').pack()
tk.Label(frm_l, text='on the frm_l2').pack()
tk.Label(frm_r, text='on the frm_r1').pack()
window.mainloop()

Message弹窗

tk.messagebox.showinfo(title=’’,message=’’)#提示信息对话窗
tk.messagebox.showwarning()#提出警告对话窗
tk.messagebox.showerror()#提出错误对话窗
tk.messagebox.askquestion()#询问选择对话窗

注意是小写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import tkinter as tk
import tkinter.messagebox

window = tk.Tk()
window.title('my window')
window.geometry('200x200')

def hit_me():
#tk.messagebox.showinfo(title='Hi', message='hahahaha') # return 'ok'
#tk.messagebox.showwarning(title='Hi', message='nononono') # return 'ok'
#tk.messagebox.showerror(title='Hi', message='No!! never') # return 'ok'
#print(tk.messagebox.askquestion(title='Hi', message='hahahaha')) # return 'yes' , 'no' 有返回值
#print(tk.messagebox.askyesno(title='Hi', message='hahahaha')) # return True, False
print(tk.messagebox.asktrycancel(title='Hi', message='hahahaha')) # return True, False
print(tk.messagebox.askokcancel(title='Hi', message='hahahaha')) # return True, False
print(tk.messagebox.askyesnocancel(title="Hi", message="haha")) # return, True, False, None

tk.Button(window, text='hit me', command=hit_me).pack()
window.mainloop()

pack,grid,place放置位置

pack(),参数是side

1
2
3
4
tk.Label(window, text='1').pack(side='top')#上
tk.Label(window, text='1').pack(side='bottom')#下
tk.Label(window, text='1').pack(side='left')#左
tk.Label(window, text='1').pack(side='right')#右

grid
接下里我们在看看grid(), grid 是方格, 所以所有的内容会被放在这些规律的方格中.
以上的代码就是创建一个四行三列的表格,其实grid就是用表格的形式定位的。这里的参数 row为行,colum为列,padx就是单元格左右间距,pady就是单元格上下间距。

1
2
3
for i in range(4): #行
for j in range(3): #列
tk.Label(window, text=1).grid(row=i, column=j, padx=10, pady=10) #内部拓展,ipadx

place
再接下来就是place(), 这个比较容易理解,就是给精确的坐标来定位,如此处给的(20,10),就是将这个部件放在坐标为(x,y)的这个位置 后面的参数anchor=nw就是前面所讲的锚定点是西北角。

1
tk.Label(window, text=1).place(x=20, y=10, anchor='nw') 

登录窗口

https://morvanzhou.github.io/tutorials/python-basic/tkinter/3-03-example3/

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
import tkinter as tk
from tkinter import messagebox # import this to fix messagebox error
import pickle

window = tk.Tk()
window.title('Welcome to Mofan Python')
window.geometry('450x300')

# welcome image
canvas = tk.Canvas(window, height=200, width=500)
image_file = tk.PhotoImage(file='welcome.gif')
image = canvas.create_image(0,0, anchor='nw', image=image_file)
canvas.pack(side='top')

# user information
tk.Label(window, text='User name: ').place(x=50, y= 150)
tk.Label(window, text='Password: ').place(x=50, y= 190)

var_usr_name = tk.StringVar()
var_usr_name.set('example@python.com')
entry_usr_name = tk.Entry(window, textvariable=var_usr_name)
entry_usr_name.place(x=160, y=150)
var_usr_pwd = tk.StringVar()
entry_usr_pwd = tk.Entry(window, textvariable=var_usr_pwd, show='*')
entry_usr_pwd.place(x=160, y=190)

def usr_login():
usr_name = var_usr_name.get()
usr_pwd = var_usr_pwd.get()
try:
with open('usrs_info.pickle', 'rb') as usr_file:
usrs_info = pickle.load(usr_file)
except FileNotFoundError:
with open('usrs_info.pickle', 'wb') as usr_file:
usrs_info = {'admin': 'admin'}
pickle.dump(usrs_info, usr_file)
if usr_name in usrs_info:
if usr_pwd == usrs_info[usr_name]:
tk.messagebox.showinfo(title='Welcome', message='How are you? ' + usr_name)
else:
tk.messagebox.showerror(message='Error, your password is wrong, try again.')
else:
is_sign_up = tk.messagebox.askyesno('Welcome',
'You have not signed up yet. Sign up today?')
if is_sign_up:
usr_sign_up()

def usr_sign_up():
def sign_to_Mofan_Python():
np = new_pwd.get()
npf = new_pwd_confirm.get()
nn = new_name.get()
with open('usrs_info.pickle', 'rb') as usr_file:
exist_usr_info = pickle.load(usr_file)
if np != npf:
tk.messagebox.showerror('Error', 'Password and confirm password must be the same!')
elif nn in exist_usr_info:
tk.messagebox.showerror('Error', 'The user has already signed up!')
else:
exist_usr_info[nn] = np
with open('usrs_info.pickle', 'wb') as usr_file:
pickle.dump(exist_usr_info, usr_file)
tk.messagebox.showinfo('Welcome', 'You have successfully signed up!')
window_sign_up.destroy()
window_sign_up = tk.Toplevel(window)
window_sign_up.geometry('350x200')
window_sign_up.title('Sign up window')

new_name = tk.StringVar()
new_name.set('example@python.com')
tk.Label(window_sign_up, text='User name: ').place(x=10, y= 10)
entry_new_name = tk.Entry(window_sign_up, textvariable=new_name)
entry_new_name.place(x=150, y=10)

new_pwd = tk.StringVar()
tk.Label(window_sign_up, text='Password: ').place(x=10, y=50)
entry_usr_pwd = tk.Entry(window_sign_up, textvariable=new_pwd, show='*')
entry_usr_pwd.place(x=150, y=50)

new_pwd_confirm = tk.StringVar()
tk.Label(window_sign_up, text='Confirm password: ').place(x=10, y= 90)
entry_usr_pwd_confirm = tk.Entry(window_sign_up, textvariable=new_pwd_confirm, show='*')
entry_usr_pwd_confirm.place(x=150, y=90)

btn_comfirm_sign_up = tk.Button(window_sign_up, text='Sign up', command=sign_to_Mofan_Python)
btn_comfirm_sign_up.place(x=150, y=130)

# login and sign up button
btn_login = tk.Button(window, text='Login', command=usr_login)
btn_login.place(x=170, y=230)
btn_sign_up = tk.Button(window, text='Sign up', command=usr_sign_up)
btn_sign_up.place(x=270, y=230)

window.mainloop()

pickle模块

pickle 是一个 python 中, 压缩/保存/提取 文件的模块. 最一般的使用方式非常简单. 比如下面就是压缩并保存一个字典的方式. 字典和列表都是能被保存的.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import pickle

a_dict = {'da': 111, 2: [23,1,4], '23': {1:2,'d':'sad'}}

# pickle a variable to a file
file = open('pickle_example.pickle', 'wb') #wb 是以写的形式打开
pickle.dump(a_dict, file) #装载的是a_dict,装在flie里面(固定在文件列表里面),就有一个pickle_example.pickle
file.close()

# reload a file to a variable
with open('pickle_example.pickle', 'rb') as file: #rb 是读的形式打开,with不用考虑关闭file.close()
a_dict1 =pickle.load(file)

print(a_dict1)