Python基础


一、Python基础语法

1.1 基本运算

1.1.1 取幂运算

a=100
a**=10  			#10000

1.1.2 除以

a/=10 				#10.0

1.1.3 整除

a//9  				#11

1.2 字符串的定义与相关操作

1.2.1 字符串的定义

字符串在Python中有多种定义形式:

  • 单引号定义法
  • 双引号定义法
  • 三引号定义法:与多行注释的写法一样,同样支持换行操作
    • 使用变量接收它,它就是字符串
    • 不使用变量接收它,就可以作为多行注释使用

1.2.2 字符串的引号嵌套

  • 单引号定义法,可以内含双引号
  • 双引号定义法,可以内含单引号
  • 可以使用转义字符”\“来将引号解除效用
    • 例:name = "\"黑马程序员\""

1.2.3 字符串的拼接

使用”+“号连接字符串变量或字符串字面量即可,但无法和非字符串类型进行拼接

1.2.4 索引

word='Python'
word[0] #'P'
word[-1] #'n'

1.3 字符串的格式化与对齐

字符串的拼接有明显的劣势:

  • 变量过多,拼接起来较麻烦
  • 字符串无法和数字或其他类型完成拼接

1.3.1 占位型拼接

  • %s表示:占位
  • s表示:将变量变成字符串放入占位的地方
name = "黑马程序员"
message = "学IT就来 %s" %name
print(message)

多个变量占位,变量要用括号括起来,并按照占位的顺序填入:

class_num = 57
avg_salary = 16781
message = "Python大数据学科,北京%d期,毕业平均工资:%d" % (class_num,avg_salary)
print(message)

可以使用辅助符号”m.n“来控制数据的宽度精度

  • m控制宽度,要求是数字(设置的宽度小于数字自身将不生效)
  • .n控制小数点精度,要求是数字,会进行小数的四舍五入

1.3.2 快速格式字符串的方式

f"内容{变量}"(f意为format)

这种方式不理会类型,且不作精度控制,适合对精度没有要求的时候快速使用。

1.3.3 对齐字符串

  • ^ :居中,后面带宽度

  • < :左对齐,后面带宽度

  • > :右对齐,后面带宽度

  • : 后面带填充的字符,只能是一个字符,不指定则是默认用空格填充

print("{:>5}".format(1))  			#宽度为5,右对齐
print("{:>5}".format(10))
print("{:>5}".format(100))
print("{:>5}".format(1000))

输出结果为:

   1
  10
 100
1000
数字 格式 输出 描述
3.1415926 {:.2f} 3.14 保留小数点后两位
3.1415926 {:+.2f} +3.14 带符号保留小数点后两位
-1 {:-.2f} -1.00 带符号保留小数点后两位
2.71828 {:.0f} 3 不带小数
5 {:0>2d} 05 数字补零 (填充左边, 宽度为2)
5 {:x<4d} 5xxx 数字补x (填充右边, 宽度为4)
10 {:x<4d} 10xx 数字补x (填充右边, 宽度为4)
1000000 {:,} 1,000,000 以逗号分隔的数字格式
0.25 {:.2%} 25.00% 百分比格式
1000000000 {:.2e} 1.00e+09 指数记法
13 {:>10d} 13 右对齐 (默认, 宽度为10)
13 {:<10d} 13 左对齐 (宽度为10)
13 {:^10d} 13 中间对齐 (宽度为10)
11 '{:b}'.format(11) '{:d}'.format(11) '{:o}'.format(11) '{:x}'.format(11) '{:#x}'.format(11) '{:#X}'.format(11) 1011 11 13 b 0xb 0XB 进制
# 正号表示正数
print("{:+2f}".format(3.14))            #+3.140000
print("{:-2f}".format(-1))              #-1.000000
# 不带小数的
print("{:.0f}".format(3.23123131))      #3
# 以逗号为分隔符的
print("{:,}".format(100000))            #100,000
# 表示一个百份比
print("{:.2%}".format(0.25))            #25.00%

1.4 切片操作

简单切片指的是这样的切片形式:a[start:stop],其行为是得到下标在这样一个前闭后开区间范围内的元素,其中startstop为负数时,简单看作是负数下标对应的位置即可。

word[0:2]  			#'Py'相当于数学中的[0,2)
z = [1,2,3,4,5]
z[:-1]				#[1, 2, 3, 4]

1.5 Python中的基本概念

  • 列表list
x1=[1,2,3,4]
  • 元组Tuple
x2=(1,2,3,4,5,6,7)
  • 步长
print(x2[1::2])  #第三个参数代表步长,答案为(2,4,6)
  • 序列重复
x3="123"*5  #123123123123123

二、列表

列表的下标索引,从前向后从0开始,每次+1;从后向前从-1开始,每次-1

2.1 追加元素

#一个元素
x1.append("Hello") #仅对列表使用append,[1,2,3,4,"Hello"]
#追加多个元素
x1.extend([6,7]) 

2.2 中间插入元素

x1.insert(2,"GREAT") #x1=[1, 2, 'GREAT', 3, 4, 'Hello', 6, 7]

2.3 删除元素

x1.remove(3) 			#remove会删除查找到的第一个元素,并且没有返回值
del x1[2]     			#删除指定元素
element = x1.pop(2)		#取出(并删除)元素,并用一变量接收返回值

2.4 反转列表

x1.reverse()

2.5 排序

x1.sort()

三、元组

元组一旦定义完成,就不可修改

特例:

可以修改元组内的list内容(修改元素、增加、删除、反转等)。

3.1 只有一个元素的元组定义

a1=("Hello",)
print(a1,type(a1))  	#<class 'tuple'>

3.2 统计某元素在元组中出现的次数

a1.count("Hello")

3.3 元组的嵌套

t = ((1,2,3),(4,5,6))
num = t[1][2]			#6

注:

元组支持for循环。

四、字典

4.1 格式

​ 每个元素均由”:“和键值对构成,”:“左边称为键(Key),右边称为值(Value)。

english=
{
	"we":"我们",
    "world":"世界",
    "company":"公司"
}
print(english,type(english)) #运行结果为:{'we':'我们','world':'世界','company':'公司'} <class 'dict'>
english["world"]="城市"  #修改/增加元素

4.2 删除、清空与拷贝

del english["city"]  #删除元素
english.clear()  #清空元素
english1=english.copy()  #复制一个具有相同键值对的字典

4.3 创建新词典

seq=("name","age","class")
stu1=dict.fromkeys(seq)
print("不指定默认值",stu1)  #{'name':None,'age':None,'Class':None}
stu2=dict.fromkeys(seq,15)
print("指定默认值",stu2)  #{'name':15,'age':15,'Class':15}

4.4 返回键对应的值

print(english.get("world"))  #输出"世界",若字典中没有则返回None,可以指定默认值,如下
print(english.get("city","未知")) #输出"未知"
print(english.keys()) #输出:dict_key(['we','world','company']),keys方法常用来判断一个键是否存在于字典中
print("是否存在world?","world" in english.keys()) #True

4.5 返回列表

print(english.items())  #输出:dict_items([('we','我们'),('world','世界'),('company','公司')])

4.6 遍历字典

for k,v in english.items():
    print(k,"->",v)
#输出:we->我们
#     world->世界
#     company->公司

五、集合

5.1 集合的格式

empty = set()   					#空集合
number = {1,2,3}  					#数字集合
mix = set([1,"您好",3.14]) 		   #混合类型集合,输出{3.14,1,'您好'}

5.2 集合的基本操作

集合的基本操作主要有增加,减少,取交、并、差等。

number = {1,2,3}
number.add(5)  						#{1,2,3,5},增加元素可以增加重复的(相当于不增加)
number.remove(3) 					#{1,2},减少元素不可以用于不存在的元素,不然会报错

n1={1,3,5},n2={2,7,1,3}:

  • 交:n1&n2 ,结果是{1,3}
  • 并:n1|n2,结果是{1,2,3,5,7}
  • 差:n1-n2,结果是{5}
  • 对称差:n1^n2,结果是{2,5,7}

六、推导式(解析式)

6.1 列表推导式

odd=[x for x in range(10) if x%2!=0]
print(odd)  #输出为[1,3,5,7,9]

6.2 字典推导式

d1={n:n**2 for n in range(5)}
print(d1)  #{0:0,1:1,2:4,3:9,4:16}
d2={v:k for k,v in d1.items()}
print(d2)  #{0:0,1:1,4:2,9:3,16:4}

6.3 集合推导式

s1={i**2 for i in [-1,-5,1,2,-2]}
print(s1)  ##{1,4,25},推导时可以去除重复元素

七、流程控制

7.1 if判断

格式:

x=True
if x: #表达式
    print("It is True!") 

elif,else

7.2 while循环

x=1
while x<=10:
    print(x)
    x+=1

7.3 for循环

for x in (1,2,3,4,5)
    print(x)  #输出1 2 3 4 5(每个都将会换行)
for x in range(5)  #range也可指定开始和结束数字,如range(1,10),输出从1到9
    print(x)  #输出0 1 2 3 4 5(每个都将会换行),注意从0开始

range还可以指定序列步长,如range(1,10,2),即为1,3,5,7,9(每个都将会换行)。

ps:pass语句,不执行任何操作,其作用是保持程序结构的完整性

如:

if i==3:
    pass
else:
    print(i)

whilefor后可以跟else,当跳出循环时会执行else的语句。但如果是因为break产生的跳出循环,则不会执行else的语句。

八、函数

8.1 可变参数

(1)*args参数:获取到的是一个元组

def foo(*args):
    print(args)
foo(1,"Shanghai") #输出(1,'Shanghai')

(2)**kwargs参数:获取到的是一个字典

def foo(**kwargs):
    print(kwargs)
foo(name='Jack')  #输出{'name':'Jack'}

(3)组合使用

def cal(*args,**kwargs)
	s=0
    for i in args:
    	s+=i
    print("输入的数字之和为",s)
    for k,v in kwargs.items():
        print(k,v)
cal(1,2,3,4,5,姓名="Jack") #结果为:输入的数字之和为15  姓名Jack

8.2 函数的多返回值

def test():
    return 1,2
x,y = test()
print(x)		#1
print(y)		#2

8.3 函数的多种传参方式

8.3.1 位置参数

调用函数时根据函数定义的参数位置来传递参数。

8.3.2 关键字参数

def user_info(name,age,gender):
	print(f"您的名字是:{name},年龄是:{age},性别是:{gender}")

#关键字传参
user_info(name="小明",age=20,gender="男")
#可以不按照固定顺序
user_info(age=20,gender="男",name="小明")
#可以和位置参数混用,位置参数必须在前,且匹配参数顺序
user_info("小明",age=20,gender="男")

8.3.3 缺省参数

def user_info(name,age,gender='男'):
	print(f"您的名字是:{name},年龄是:{age},性别是:{gender}")

user_info(name="小明",age=20)

8.4 函数作为参数传递

函数作为参数传递是一种计算逻辑的传递,计算逻辑由被传入函数决定,而非数据的传递。

def test_func(compute):
    result = compute(1,2)	#确定compute是函数
    print(result)
def compute(x,y):
    return x + y
test_func(compute)

8.5 lambda匿名函数

lambda关键字,可以定义匿名函数(无名称)。匿名函数只可以临时使用一次

匿名函数定义语法:lambda 传入参数 : 函数体

注:

函数体就是函数的执行逻辑,只能写一行,无法写多行代码。

def test_func(compute):
    result = compute(1,2)	#确定compute是函数
    print(result)
test_func(lambda x,y: x + y)

8.6 filter函数

filter函数是内置函数,用于过滤序列,即过滤掉不符合条件的元素。

a1=[1,2,3,4,5,6,7,8]
a2=[item for item in filter(lambda x:x>5,a1)]
print(a2)  #[6,7,8]

8.7 内置函数__call__()

Python中一切皆对象,函数也是对象,同时也是可调用对象(callable)。

一个类实例要变成一个可调用对象,只需要实现一个特殊方法__call__()

允许一个类的实例像函数一样被调用。实质上说,这意味着**x()x.__call__()是相同的**。注意__call__参数可变。这意味着你可以定义__call__()为其他你想要的函数,无论有多少个参数。

class Entity:
    def __init__(self, size, x, y):
        self.x, self.y = x, y
        self.size = size

    def __call__(self, x, y):
        '''改变实体的位置'''
        self.x, self.y = x, y

e = Entity(1, 2, 3)
print(e.x)
print(e.y)

e(4, 5)
print(e.x)
print(e.y)

8.8 函数注释

格式为:(参数注释+返回值注释)

def function_name(a:expression,b:expression)->expression:
    function body
return value

若需要获取函数注释,可以使用__annotations__的方法:

print(function_name.__annotations__)

九、类和对象

9.1 类的属性

在Python中,构造函数就是类的__init__方法,当一个类定义了__init__方法后,类在实例化时会自动调用__init__方法,用于创建新的类实例。在构造方法中我们可以初始化一些属性(或称成员变量、类变量)。

class Dog:
    def __init__(self,name)
    	self.name=name
        self.age=3
dog=Dog("旺财")
print(dog.name) #旺财
print(dog.age)  #3

类中定义的方法第一个参数必须是“self”,即def play(self)

私有属性可用dog.__name加两条下划线的形式,只能在类内进行修改。私有方法同理。

9.2 继承

定义要从哪个父类继承,只需在定义子类的名字后面的括号中填入父类的名字即可,如:

class Animal:
    def __init__(self,name)
    	self.name=name
        self.age=3
class Dog(Animal):
    pass

9.3 多态

多态的意思就是多种形态。多态意味着即使不知道变量所引用的对象是什么类型,也能对对象进行操作。多态会根据类的不同表现出不同的行为。

9.3.1 继承方式实现多态

class Animal:
    def say(self):
        print("Animal")
class Dog(Animal):
    def say(self):
        print("Dog")
class Cat(Animal):
    def say(self):
        print("Cat")
dog=Dog()
dog.say()  #Dog
cat=cat()
cat.say()  #cat

ps:判断一个实例是否是某个对象可以用isinstance函数,格式为isinstance(dog,Dog),返回TrueorFalse

9.3.2 函数参数实现多态

#接上例
def animal_say(animal:Animal)
	animal.say()
animal_say(dog)
animal_say(cat)

9.3.3 鸭子类型

​ 鸭子类型中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口决定的,而是由当前方法和属性的集合决定的。

class Dog:
	def say(self):
        print("Dog")
class Cat:
    def say(self):
        print("Cat")
def animal_say(animal): #编写一个函数,使它接受一个类型为鸭子的对象
    animal.say()
dog=Dog()
cat=Cat()
animal_say(dog)

9.4 静态方法和类方法

9.4.1 静态方法

​ 定义静态方法时,在定义函数的上面一行添加“@staticmethod”,且静态方法不再有第一个默认参数“self”,本身也不能调用成员变量和成员方法。

class Animal
	name="动物"
    @staticmethod
    def play()
    	print("Playing")
Animal.play()

9.4.2 类方法

​ 类方法将该方法绑定在定义的类上,而不是绑定在实例上。在定义函数的上面一行添加“@classmethod”,有初始参数”cls“,类方法指向的是定义的类本身,类方法可以读取和修改类变量。

class Animal
	name="动物"
    @classmethod
    def play(cls)
    	print(c"Playing")
Animal.play()

十、模块

模块就是一个包含了Python定义和声明的”.py”文件。在完成一个”.py”文件后,在与其同目录的文件可以使用这个模块,即import fibs。如果要导入模块中的一个指定的部分到当前命名空间中,可用from fibs import fib,fib2

10.1 获取模块名

模块的模块名可以通过全局变量”__name__“获得。

import fibs
print(fibs.__name__)  #fibs
print(__name__)       #__main__

由此可知,在定义模块时,可通过看当前的”__name__“变量是否为”__main__“来判断当前文件是被运行还是作为模块被导入。

if __name__=="__main__"
	print("直接运行")
else:
    print("被作为模块导入")

10.2 dir函数

dir函数可以列出对象的模块标识符,包括函数、类和变量。模块也是对象,调用模块中的内容和调用对象中的内容的方法是一样的。

import fibs
	fibs.fib(10)
print(fibs.fib2(5))

10.3 包

模块即一个py文件,通过“包”加以组织。“包”是一个包含模块,且至少包含一个__init__.py的文件夹,模块中包含代码。

package9
|--__init__.py
|--fun1.py
|--fun2.py

package9/fun1.py:

def print1():
    print("fun1")

package9/fun2.py:

def print2():
    print("fun2")

__init__.py:

if __name__ == "__main__":
    print("作为主程序运行")
else:
    print("package初始化")

demo.py

#导入package9包
from package9.fun1 import print1
from package9.fun2 import print2
print1()
print2()

10.4 常用标准库

10.4.1 math库

两个常量:圆周率和自然常数e,调用方式为:math.pi,math.e

运算函数:向上取整,如math.ceil(1.7),结果为2;向下取整,如math.floor(1.7),结果为1。

​ 对数函数(默认底数为e,可使用第二个参数来改变对数的底数)

​ 平方根计算(sqrt),三角函数计算,角度(degree)弧度(radians)转换

10.4.2 random库

random.random用于生成一个0-1的随机浮点数:0<=n<1.0

random.uniform(1,150)用于生成一个指定范围内的随机浮点数。

random.choice(seq1)会从给定的序列中获取一个随机元素。

import random
seq1=(1,15,8,97,22)
seq2=["星期日","星期一","星期二","星期三","星期四","星期五","星期六"]
print(random.choice(seq1))
print(random.choice(seq2))

random.shuffle(seq1)用于将一个列表中的元素打乱(注意:原来的序列必须是可以修改的,故元组等类型不能作为其参数使用)。

十一、文件操作与IO

11.1 文件基本操作

打开文件:

file_name="10.1.py"
f=open(file_name)

文件模式:r+,表示打开一个文件用于读写,文件指针将会放在文件的开头。

使用open函数返回的是一个文件对象,然后通过使用read方法从一个打开的文件中读取内容到字符串。写文件则用write方法。write方法返回写入文件的字符串的长度。

f=open("readme.txt")
txt=f.read()
print(txt)

若想在已有的文件内容后追加内容,可在打开文件时使用”a“模式,这样就可以在文件中追加写入内容。

关闭文件用f.close()

11.2 按行读/写文件

11.2.1 按行读取文件内容

f.readline()

readlines函数会将文件内容按行切割,返回一个list列表对象。(注意:readlines函数会保留结尾的换行符,不会去掉换行符,直接print列表元素会发现每次输出都跟随一个空白行)

f=open("a.txt","r+")
for line in f.readlines():
    print(line)

此外还有直接迭代文件对象本身的操作:这是一种”惰性“读取文件的方式,只有迭代到需要读取的一行,才会真的执行读取操作。

f=open("a.txt","r+")
for line in f:
    print(line)

11.2.2 按行写入文件内容

利用writelines方法接收一个参数(必须是列表),列表的每个元素就是想写入的每行文本的内容。

f=open("writelines.txt","r+")
lines=[]
for i in range(10):
    lines.append(str(i))
f.writelines(lines)

运行结果为0123456789,说明其不会帮助我们在每行之后添加换行符。

i=1
f=open("numbers.txt","a")  #利用追加模式,参数从w替换为a即可
while i <= 10:    
    f.write("{}\n".format(i)) #format()为格式化字符串的函数
    i=i+1
f.close()

11.3 StringIO函数

对str操作,要把str写入StringIO,需要先创建一个StringIO对象,然后像文件一样写入即可。

from io import StringIO
f=StringIO()
f.write('hello')
f.write(' ')
f.write('world!')
print(f.getvalue()) #获得写入后的str,输出hello world!

要读取StringIO,可以先用一个str初始化StringIO,然后像读文件一样读取。其中strip()方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。若参数不为空,则移除所有该参数,如print str.strip( '0' ); #去除首尾字符 0

from io import StringIO
f=StringIO('Hello!\nWorld!\nWelcome!\n')
while True:
    s=f.readline()
    if s=='':
        break
    print(s.strip()) 

11.4 BytesIO函数

from io import BytesIO
f=BytesIO()
f.write("您好".encode("utf-8")) #以指定的编码格式编码字符串
print(f.getvalue())
print(f.getvalue().decode("utf-8")) #以指定的编码格式解码字符串

输出结果如下:b'\xe6\x82\xa8\xe5\xa5\xbd'

您好

读取方式如下:

from io import BytesIO
f=BytesIO(b'\xe6\x82\xa8\xe5\xa5\xbd')
print(f.read().decode("utf-8"))  #输出"中文"

11.5 序列化与反序列化

pickle.dumps可以把任意对象序列化成bytes对象,然后写入文件中永久存储。

import pickle
class Student:
    def __init__(self,name,age,gender):
        self.name=name
        self.age=age
        self.gender=gender
student1=Student("小明",15,"男")
print(pickle.dumps(student1))

十二、日期和时间

12.1 time函数

​ time函数用于返回当前时间的时间戳,time函数返回的是浮点数。

import time
now=time.time()
print("当前的时间戳是:%f" % now)

输出结果为:当前的时间戳是:1641976277.347599

12.2 localtime函数

localtime函数的作用是将时间戳格式化为本地时间,返回struct_time对象。localtime函数有一个参数用于接收时间戳,如果调用函数时不提供时间戳, localtime函数默认使用当前时间戳。

import time
print("当前时间",time.localtime())
print("0时间戳对应的时间",time.localtime(0))

12.3 datetime模块

​ datetime模块包含了日期和时间的所有信息。

12.3.1 date对象

表示在日历中的一个日期(包含年、月、日)。格式为date=datetime.date(2018,7,1)

12.3.2 一些方法

Today方法/weekday方法分别返回当天日期和当前星期数(星期一返回0,依此类推)。isoweekday方法星期一返回1,依此类推。isoformat方法返回日期格式为ISO格式,即“YYYY-MM-DD”字符串。strftime方法可以格式化输出日期,如print(date.strftime("%Y-%m-%d"))。对于时-分-秒,分别为%H:%M:%S

十三、多线程和并行

​ 多线程是指在软件或者硬件上实现多个线程并发执行的技术。Python标准库中关于线程的主要是_threadthreading模块。

13.1 _thread模块

13.1.1 概述

​ 核心是start_new_thread方法,格式为:_thread.start_new_thread(function,args[,kwargs])。线程使用参数列表args(必须是元组)执行函数,可选的kwargs参数指定关键字参数的字典。在单个线程执行时,别的线程也在”同步“地执行。

import time
import datetime
import _thread
date_time_format="%H:%M:%S"
def get_time_str():
    now=datetime.datetime.now()
    return datetime.datetime.strftime(now,date_time_format)
def thread_function(thread_id):
    print("Thread %d\t start at %s"%(thread_id,get_time_str()))
    print("Thread %d\t sleeping"%thread_id)
    time.sleep(4)
    print("Thread %d\t finish at %s"%(thread_id,get_time_str()))
def main():
    print("Main thread start at %s"%get_time_str())
    for i in range(5):
        _thread.start_new_thread(thread_function,(i,))
        time.sleep(1)
    time.sleep(6)
    print("Main thread finish at %s"%get_time_str())
if __name__ =="__main__":
    main()

运行结果如下:

Main thread start at 17:44:03
Thread 0	 start at 17:44:03
Thread 0	 sleeping
Thread 1	 start at 17:44:04
Thread 1	 sleeping
Thread 2	 start at 17:44:05
Thread 2	 sleeping
Thread 3	 start at 17:44:06
Thread 3	 sleeping
Thread 0	 finish at 17:44:07
Thread 4	 start at 17:44:07
Thread 4	 sleeping
Thread 1	 finish at 17:44:08
Thread 2	 finish at 17:44:09
Thread 3	 finish at 17:44:10
Thread 4	 finish at 17:44:11
Main thread finish at 17:44:14

13.1.2 线程锁

_thread.allocate_lock方法返回一个Lock对象。Lock对象有三个方法:

【1】acquire方法:用于无条件地获取Lock对象(如果有必要,等待他被另一个线程释放,一次只有一个线程可以获取锁定)。

【2】release方法:用于释放锁,释放之前必须先锁定,

【3】locked方法:用于返回锁的状态,如果已被某个线程锁定,则返回True,否则返回False。

lock=_thread.allocate_lock()
lock.acquire()
locks.append(lock)

13.2 Threading模块

利用threading.Thread创建线程。

import time
import datetime
import threading
date_time_format="%H:%M:%S"
def get_time_str():
    now=datetime.datetime.now()
    return datetime.datetime.strftime(now,date_time_format)
def thread_function(thread_id):
    print("Thread %d\t start at %s"%(thread_id,get_time_str()))
    print("Thread %d\t sleeping"%thread_id)
    time.sleep(4)
    print("Thread %d\t finish at %s"%(thread_id,get_time_str()))
def main():
    print("Main thread start at %s"%get_time_str())
    threads=[]
    #创建线程
    for i in range(5):
        thread=threading.Thread(target=thread_function,args=(i,))
        threads.append(thread)
    #启动线程
    for i in range(5):
        threads[i].start()
        time.sleep(1)
    #等待线程执行完毕
    for i in range(5):
        threads[i].join()  #阻塞线程,使用join后,后面的语句需要等当前进程完成之后才能执行
    print("Main thread finish at %s"% get_time_str())
if __name__ =="__main__":
    main()

运行结果如下:

Main thread start at 20:36:02
Thread 0	 start at 20:36:02
Thread 0	 sleeping
Thread 1	 start at 20:36:03
Thread 1	 sleeping
Thread 2	 start at 20:36:04
Thread 2	 sleeping
Thread 3	 start at 20:36:05
Thread 3	 sleeping
Thread 0	 finish at 20:36:06
Thread 4	 start at 20:36:06
Thread 4	 sleeping
Thread 1	 finish at 20:36:07
Thread 2	 finish at 20:36:08
Thread 3	 finish at 20:36:09
Thread 4	 finish at 20:36:10
Main thread finish at 20:36:10

文章作者: ShiQuLiZhi
版权声明: 本博客所有文章除特别声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 ShiQuLiZhi !
评论
  目录