python基础知识2

面向对象程序设计

Object Oriented Programming : OOP 面向对象程序设计

特性:封装,继承和多态

类的定义类、实例的创建、方法的定义

python的关键字比较少

面向对象程序设计入门

# 编写程序,模拟学生选课,每选一门课程,将课程名加入到学生的所选课程中,同时将课程的学分累加到学生的总学分中。

stu = {'num':'201801','name':'Jack', 'credit': 0,'course':[]}	#定义一个学生
cours1 = {'num':'01','name':'Python','credit': 3}		#定义课程1
cours2 = {'num':'02','name':'C','credit': 4}		#定义课程2

def choose(c):				#定义实现选课功能的函数
    stu['credit']+=c['credit']			#将课程的学分累加到学生的总学分中
    stu['course'].append(c['name'])		#将课程名加入到学生的所选课程中

choose(cours1)				#学生选课程1
choose(cours2)				#学生选课程2
print(stu)					#输出学生信息

此时最好的解决方法就是采用面向对象程序设计思路进行编程。使用面向对象思路实现上述问题时,可以将“学生”和“课程”分别看作两类对象,具体如下:

学生类:其特征包括学号、姓名、总学分和所选课程,行为包括选课;
课程类:其特征包括课程编号、课程名和学分。

有了这样的类后,我们可以很轻松地实例化多个学生和多门课程,执行选课操作时,也限制了只有学生能够进行选课操作。

总的来说,面向对象程序设计是一种解决代码复用的编程方法。这种方法把软件系统中相似的操作逻辑、数据和状态以类的形式描述出来,以对象实例的形式在软件系统中复用,以达到提高软件开发效率的目的。

类的的定义与使用

在面向对象编程中,最重要的两个概念就是对象(也称为实例)。

  • 对象是某个具体存在的事物 (例如,一个名叫“Jack”的学生就是一个对象)
  • 与对象相比,是抽象的,它是对一群具有相同特征和行为的事物的统称 (例如,学校的学生,其特征包括“学号”“姓名”“性别”等,其行为包括“选课”“上课”“考试”等)

我们在前面的章节中已经用了很长时间的类和对象了。例如,字典类型的本质就是类。

print(type(dict))				#查看字典类型
# <class 'dict'>

stu = dict(num = '20180101', name = 'Liming', sex = 'male')#创建类的对象
print(stu.pop('name'))		#执行stu的方法
# 'Liming'
类的定义

面向对象程序设计思想把事物的特征和行为包含在类中。其中,事物的特征作为类中的变量,事物的行为作为类的方法,而对象是类的一个实例

# 格式:
class 类名:
    类体

# (1)类名的首字母一般需要大写,如Car。
# (2)类体一般包括变量的定义和方法的定义。
# (3)类体相对于class关键字必须保持一定的空格缩进。

# 例子:
#定义类
class Car:	
    price = 150000		#定义价格变量
    def run(self):		#定义行驶方法
        print('车在行驶中……')

创建类的对象
  1. 在Python中,创建对象的语法格式如下:
对象名 = 类名()
  1. 创建完对象后,可以使用它来访问类中的变量和方法,具体方法是:
对象名.类中的变量名
对象名.方法名([参数])
# 例子:
class Car:	
    price = 150000		#定义价格变量
    def run(self):		#定义行驶方法
        print('车在行驶中……')
car_1 = Car()		#创建一个对象,并用变量car_1保存它的引用
car_1.run()		#调用run()方法
print('车的价格是:',car_1.price)	#访问类中的变量
self参数

类的所有方法都必须至少有一个名为self的参数,并且必须是方法的第1个参数

在Python中,由同一个类可以生成无数个对象,当一个对象的方法被调用时,对象会将自身的引用作为第一个参数传递给该方法,那么Python就知道需要操作哪个对象的方法了。

class Car:	
    def color(self,col):			#定义赋值颜色方法
        self.col=col				#赋值
    def show(self):				#定义显示颜色方法
        print('The color of the car is %s.'%self.col)	#输出颜色
car_1 = Car()				#创建对象car_1
car_1.color('red')				#调用方法
car_2 = Car()				#创建对象car_2
car_2.color('white')			#调用方法
car_1.show()				#调用方法
car_2.show()				#调用方法

注意:在类的方法中访问变量时,需要以self为前缀,但在外部通过对象名调用对象方法时不需要传递该参数。

构造方法

构造方法的固定名称为**init(),当创建类的对象时,系统会自动调用**构造方法,从而实现对对象进行初始化的操作。

# 例子:
#定义类
class Car:
#构造方法
    def __init__(self):
        self.wheelNum = 4
        self.colour = '蓝色'
#方法
    def run(self):
        print('{}个轮子的{}车在行驶中……'.format(self.wheelNum, self.colour))
BMW = Car()				#创建对象
BMW.run()				#调用方法
#定义类
class Car:
#构造方法
    def __init__(self,wheelNum,colour):
        self.wheelNum = wheelNum
        self.colour = colour
#方法
    def run(self):
        print('{}个轮子的{}车在行驶中……'.format(self.wheelNum, self.colour))
BMW = Car(4,'红色')			#创建对象
Audi = Car(4,'白色')			#创建对象
BMW.run()				#调用方法
Audi.run()				#调用方法
# 例:用面向对象程序设计思路编写程序,模拟学生选课,每选一门课程,将课程名加入到学生的所选课程中,同时将课程的学分累加到学生的总学分中。

#定义学生类
class Stu:
    #构造方法定义学生属性
    def __init__(self,num,name,credit,course):
        self.num = num
        self.name = name
        self.credit  = credit
        self.course = course
    #定义学生选课方法
    def choose(self,c):	
        self.credit+=c.credit
        self.course.append(c.name)

#定义课程类
class Cou:
 #构造方法定义课程属性
    def __init__(self,num,name,credit): 	
        self.num = num
        self.name = name
        self.credit  = credit

# 创建对象
stu_1 = Stu('201801','Jack',0,[])	#创建学生1
stu_2 = Stu('201802','Tom',3,['Math'])	#创建学生2
cou_1 = Cou('01','Python',3)		#创建课程1
cou_2 = Cou('02','C',4)		#创建课程2
stu_1.choose(cou_1)		#调用方法实现学生1选课程1
stu_2.choose(cou_2)		#调用方法实现学生2选课程2
#输出各学生信息
print('学号:',stu_1.num,'姓名:',stu_1.name,'总学分:',stu_1.credit,'所选课程',stu_1.course)
print('学号:',stu_2.num,'姓名:',stu_2.name,'总学分:',stu_2.credit,'所选课程',stu_2.course)
析构方法

当需要删除一个对象来释放类所占的资源时,Python解释器会调用另外一个方法,这个方法就是析构方法。析构方法的固定名称为**del()**。

  • 程序结束时会自动调用该方法;
  • 也可以使用del语句手动调用该方法删除对象。

比较下面两个程序,分析输出结果。

class Animal():
    #构造方法
    def __init__(self):
        print('---构造方法被调用---')
    #析构方法
    def __del__(self):
        print('---析构方法被调用---')
#创建对象
dog = Animal()
print('---程序结束---')
del dog
'''结果
---构造方法被调用---
---程序结束---
---析构方法被调用---
'''
class Animal():
    #构造方法
    def __init__(self):
        print('---构造方法被调用---')
    #析构方法
    def __del__(self):
        print('---析构方法被调用---')
#创建对象
dog = Animal()
del dog
print('---程序结束---')
'''结果
---构造方法被调用---
---析构方法被调用---
---程序结束---
'''

类成员和实例成员

类中定义的变量又称为数据成员,或者叫广义上的属性。可以说数据成员有两种:一种是实例成员(实例属性),另一种是类成员(类属性)。

  • 实例成员一般是指在构造函数__init__()中定义的,定义和使用时必须以self作为前缀;
  • 类成员是在类中所有方法之外定义的数据成员。

两者的区别是:

  • 在主程序中(或类的外部),实例成员属于实例(即对象),只能通过对象名访问;而类成员属于类,可以通过类名或对象名访问。
  • 在类的方法中可以调用类本身的其他方法,也可以访问类成员以及实例成员。

提示:
与很多面向对象程序设计语言不同,Python允许动态地为类和对象增加成员,这是Python动态类型特点的重要体现。

# 例:类成员和实例成员示例
#定义类
class Car:	
    price = 150000				#类成员
    def __init__(self,colour):
        self.colour = colour			#实例成员
car_1 = Car('红色')				#创建对象
print(car_1.price,Car.price,car_1.colour)	#访问类成员和实例成员并输出
Car.name = 'Audi'				#增加类成员
car_1.wheelNum = 4			#增加实例成员
print(car_1.wheelNum,car_1.name,Car.name)	#访问类成员和实例成员并输出
# 类中有相同名称的类成员和实例成员示例:
#定义类
class Car:	
    price = 150000			#类成员
    def __init__(self):
        self.price = 100000		#实例成员
car_1 = Car()								#创建对象
print(car_1.price,Car.price)		#访问类成员和实例成员并输出

封装

封装,就是把客观事物封装成抽象的类,并规定类中的数据和方法只让可信的类或对象操作。封装可分为两个层面

  • 第一层面的封装,创建类和对象时,分别创建两者的名称,只能通过类名或者对象名加“.”的方式访问内部的成员和方法,前面介绍的例子其实都是这一层面的封装。
  • 第二层面的封装,类中把某些成员和方法隐藏起来,或者定义为私有,只在类的内部使用,在类的外部无法访问,或者留下少量的接口(方法)供外部访问。

私有化方法:在准备私有化的数据成员或方法的名字前面加两个下划线“__”即可。

# 例子:
class A:				#定义类
    def __init__(self):
        self.__X = 10 			#定义私有变量并赋值为10
    def __foo(self): 			#定义私有方法
        print('from A')
a = A()				#创建对象
print(a.__X)			#输出私有变量值
a.__foo()				#调用私有方法 报错
'''
print(a._A__X)	#通过类名访问私有变量
a. _A__foo()	#通过类名调用私有方法
'''

注意:
Python目前的私有机制其实是伪私有,实际上,在外部可以通过“_类名__属性”访问私有变量和方法。

对于这一层面的封装(隐藏),我们需要在类中定义一个方法(也称接口函数),在它内部访问被隐藏的属性和方法,然后外部可以通过接口函数进行访问。

# 在类中增加一个方法(接口函数),实现通过调用该方法访问内部成员及内部方法

class A:			#定义类
    def __init__(self):
        self.__X = 10 		#定义私有变量并赋值为10
    def __foo(self): 		#定义私有方法
        print('from A')
    def bar(self):		#定义接口函数
        self.__foo() 		#类内部访问私有方法
        return self.__X		#返回私有变量__X的值
a = A()			#创建对象
b = a.bar()		#调用接口函数,将返回值赋给b
print(b)			#输出b的值

继承

在程序中,继承描述的是事物之间的从属关系。在继承关系中,已有的、设计好的类称为父类基类,新设计的类称为子类派生类。继承可以分为单继承多继承两大类。

单继承

在Python中,当一个子类只有一个父类时称为单继承。子类的定义如下所示:

class 子类名(父类名):

子类可以继承父类的所有公有成员和公有方法,但不能继承其私有成员和私有方法。

# 例子:
#定义一个父类
class Person:
    name = '人'
    age = 30  # __age=30
    #定义方法用于输出
    def speak(self):	
        print ('%s 说: 我 %d 岁。' %(self.name,self.age))

#定义一个子类
class Stu(Person):
    #定义方法用于修改名字
    def setName(self, newName):
        self.name = newName
    #定义方法用于输出
    def s_speak(self):
        print ('%s 说: 我 %d 岁。' %(self.name,self.age))

#测试
student = Stu()				#创建学生对象
print ('student的名字为:',student.name)	输出学生名字
print ('student的年龄为:',student.age)		#输出学生年龄
student.s_speak()				#调用子类方法用于输出
student.setName('Jack')			#调用子类方法用于修改名字
student.speak()		
多继承

多继承指一个子类可以有多个父类,它继承了多个父类的特性。多继承可以看作是对单继承的扩展,其语法格式如下:

class 子类名(父类名1,父类名2):
# 例子:
#定义沙发父类
class Sofa:
    def printA(self):
        print ('----这是沙发----')

#定义床父类
class Bed:
    def printB(self):
        print('----这是床----')

#定义一个子类,继承自Sofa和Bed
class Sofabed(Sofa,Bed):
    def printC(self):
        print('----这是沙发床----')

# 测试
obj_C = Sofabed()		#创建对象
obj_C.printA()		#调用Sofa父类中的方法
obj_C.printB()		#调用Bed父类中的方法
obj_C.printC()		#调用自身的方法

注意:
在Python中,如果两个父类中有同名的方法,调用该同名方法时会调用先继承类中的方法。[例如:如果Sofa和Bed类中有同名的方法,用“class Sofabed(Sofa,Bed):”语句定义子类时,子类会先继承Sofa类]

重写父类方法与调用父类方法
  1. 重写父类方法:
    在继承关系中,子类会自动继承父类中定义的方法,但如果父类中的方法功能不能满足需求,就可以在子类中重写父类的方法。即子类中的方法会覆盖父类中同名的方法,这也称为重载
# 例子:
#定义一个父类
class Person:
    def speak(self):		#定义方法用于输出
        print ('我是一个人类')
#定义一个子类
class Stu(Person):
    def speak(self):		#定义方法用于输出
        print ('我是一个学生')
student = Stu()		#创建学生对象
student.speak()		#调用同名方法
  1. 调用父类方法
    如果需要在子类中调用父类的方法,可以使用内置函数super()或通过“父类名.方法名()”的方式来实现。
# 例子:
#定义父类
class Person():
    def __init__(self, name, sex):
        self.name = name
        self.sex = sex
#定义子类
class Stu(Person):
    def __init__(self, name, sex, score):
        super().__init__(name, sex)	#调用父类中的__init__方法
        self.score = score
#创建对象实例
student = Stu('Jack','Male',90)
print("姓名:%s,性别:%s,成绩: %s"%(student.name,student.sex,student.score))

多态

多态指的是一类事物有多种形态,如一个父类有多个子类。
在面向对象方法中一般是这样描述多态性的:向不同的对象发送同一条消息,不同的对象在接收时会产生不同的行为(即方法)。

# 例子:
#定义父类
class Person:
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
    def who(self):		#定义who方法
        print('I am a Person, my name is %s' % self.name)

#定义学生子类
class Student(Person):
    def __init__(self, name, gender, score):
        super().__init__(name, gender)
        self.score = score
    def who(self):			#重写父类方法
        print('I am a Student, my name is %s' % self.name)

#定义教师子类
class Teacher(Person):
    def __init__(self, name, gender, course):
        super().__init__(name, gender)
        self.course = course
    def who(self):			#重写父类方法
        print('I am a Teacher, my name is %s' % self.name)

#定义函数用于接收对象
def fun(x):
    x.who()			#调用who方法
#创建对象
p = Person('Jack', 'Male')
s = Student('Tom', 'Male', 88)
t = Teacher('Lily', 'Female', 'English')
#调用函数
fun(p)
fun(s)
fun(t)

类方法和静态方法

类方法

类方法是类所拥有的方法,需要用修饰器“@classmethod”来标识其为类方法。对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数(同self一样只是一个习惯),能够通过对象名调用类方法,也可以通过类名调用类方法。

# 例子:
#定义类
class People:
    country = 'china'		#定义类成员并赋值
#类方法,用classmethod来进行修饰
    @classmethod
    def getCountry(cls):
        return cls.country		#返回类成员的值
p = People()			#创建对象
print(p.getCountry())		#通过实例名调用
print(People.getCountry())		#通过类名调用

提示:类方法可以访问类成员,但无法访问实例成员。

静态方法

要在类中使用静态方法,需在类成员方法前加上“@staticmethod”标记符,以表示下面的成员方法是静态方法。使用静态方法的好处是,不需要实例化对象即可使用该方法。
静态方法可以不带任何参数,由于静态方法没有self参数,所以它无法访问类的实例成员;静态方法也没有cls参数,所以它也无法访问类成员。静态方法既可以通过对象名调用,也可以通过类名调用。

小技巧:
类的对象可以访问实例方法、类方法和静态方法,使用类可以访问类方法和静态方法。一般情况下,如果要修改实例成员的值,直接使用实例方法;如果要修改类成员的值,直接使用类方法;如果是辅助功能,如打印菜单,则可以考虑使用静态方法。

#例子:
#定义类
class Test:
#静态方法,用@staticmethod进行修饰
    @staticmethod
    def s_print():
        print('----静态方法----')
t = Test()				#创建对象
Test.s_print()			#通过类名调用
t.s_print()				#通过对象名调用

文件操作

文件的打开和关闭

文件指存储在外部介质(如磁盘等)上有序的数据集合,这个数据集有一个名称,称为文件名。按数据的组织形式不同,可以将文件分为文本文件二进制文件两大类。

  • 文本文件一般由单一特定编码的字符组成,如UTF-8编码,内容容易统一展示和阅读。
  • 二进制文件直接由比特0和比特1组成,没有统一字符编码,文件内部数据的组织格式与文件用途有关。
文件打开

Python对文本文件和二进制文件采用统一的操作步骤:
(1)打开文件,或者新建文件;
(2)读/写文件;
(3)关闭文件。

Python内置了文件对象,通过open()函数即可按照指定模式打开指定文件,并创建文件对象,
其语法格式如下:

文件对象名 = open(文件名[,打开方式])

# 文件名:文件名亦可包含文件路径,写路径时注意斜杠问题。若路径和文件名为“c:\myfile”,应写成“c:\\myfile”。
# 打开方式:省略时默认为只读方式
文件打开方式含义如果指定的文件不存在
r(只读)打开一个文本文件,只允许读数据出错
w(只写)打开或建立一个文本文件,只允许写数据建立新文件
a(追加)打开一个文本文件,并在文件末尾增加数据建立新文件
rb(只读)以二进制格式打开一个文件,只允许读数据出错
wb(只写)以二进制格式打开或建立一个文件,只允许写数据建立新文件
ab(追加)以二进制格式打开一个文件,并在文件末尾写数据建立新文件
r+(读写)打开一个文本文件,允许读和写出错
w+(读写)打开或建立一个文本文件,允许读和写建立新文件
a+(读写)打开一个文本文件,允许读或在文件末尾追加数据建立新文件
rb+(读写)以二进制格式打开一个文件,允许读和写出错
wb+(读写)以二进制格式打开或建立一个文件,允许读和写建立新文件
ab+(读写)以二进制格式打开一个文件,允许读或在文件末尾追加数据建立新文件
文件关闭

在Python中,虽然文件会在程序退出后自动关闭,但是考虑到数据的安全性,在每次使用完文件后,都需要使用close()方法关闭文件,
其语法格式如下:

文件对象名.close()
# 例子:以只写方式打开一个名为“test.txt”的文件,然后关闭文件。

file = open('test.txt','w')		#以只写方式打开一个名为“test.txt”的文件
file.close()			#关闭文件
上下文管理语句with

Python中的with语句用于对资源进行访问,保证不管处理过程中是否发生错误或者异常,都会执行规定的**exit(清理)**操作,释放被访问的资源,常用于文件操作、数据库连接、网络通信连接、多线程与多进程同步时的锁对象管理等场合。
其语法格式如下:

with context_expression [as target(s)]:
    with-body

# context_expression : 表达式
# target(s) : 对象名
# 用于文件内容读写时,with语句的用法如下:
with open(文件名[,打开方式]) as文件对象名:
    #通过文件对象名读写文件内容语句

文件的读写

写文件
  1. write()方法 : write()方法用于向文件中写入指定字符串
# 格式:
文件对象名.write(str)

# 例子:
file = open('testfile.txt','w')
#向文件中输入字符串
file.write('Interface options\n')
file.write('Generic options\n')
file.write('Miscellaneous options\n')
file.write('Options you shouldn’t use\n')
file.close()		

"""控制台
Interface options
Generic options
Miscellaneous options
Options you shouldn’t use
"""

提示:
如果打开文件时,文件打开方式带“b”,那么写入文件内容时,str(参数)要用encode方法转为字节流形式,否则报错。file.write(‘Interface options’.encode())

  1. writelines()方法: writelines()方法用于向文件中写入一序列的字符串。这一序列字符串可以是由迭代对象产生的,如一个字符串列表
文件对象名.writelines(sequence)

# 例子:
ls = ['Environment\n','variables']	
with open('testfile.txt','a') as file:	
    file.writelines(ls)		#向文件中追加字符串列表

'''控制台
Environment
variables
'''
读文件
  1. read()方法: read()方法用于从文件中读取指定的字节数,如果未给定参数或参数为负,则读取整个文件内容
# 格式:
文件对象名.read([size])

# size为从文件中读取的字节数
# 该方法返回从文件中读取的字符串

# 例子:
with open('testfile.txt','r') as file:	#以只读方式打开原有的名为“testfile.txt”的文件
    line = file.read(10)		#读取前10个字节
    print(line)			#输出前10个字节
    print('*'*30)			#输出30个*用于分隔
    content = file.read()		#读取文件中剩余的所有内容
    print(content)			#输出	
  1. readline()方法: readline()方法用于从文件中读取整行,包括“\n”字符。如果指定了一个非负数的参数,则表示读入指定大小的字符串
# 格式:
文件对象名.readline([size])

# 例子:
with open('testfile.txt','r') as file:	#以只读方式打开原有的名为“testfile.txt”的文件
    line = file.readline()		#读取一行
    print(line)			#输出
    print('*'*30)			#输出30个*用于分隔
    line = file.readline(10)		#读取下一行的前10个字符
    print(line)			#输出
  1. readlines()方法: readlines()方法用于读取所有行(直到结束符EOF)并返回列表,列表中每个元素为文件中的一行数据
# 格式: 
文件对象名.readlines()

# 例子: 
with open('testfile.txt','r') as file:	#以只读方式打开原有的名为“testfile.txt”的文件
    content = file.readlines()	#读取所有行并返回列表
print(content)			#输出列表
print('*'*60)			#输出60个*用于分隔
for temp in content:		#遍历列表
	print(temp)		#输出列表每个元素
with open('testfile.txt','r') as file:	#以只读方式打开原有的名为“testfile.txt”的文件
for line in file:			#遍历文件的所有行
    print(line)		#输出行


# 例子2:将文件“testfile.txt“中的内容复制到另一个文件“copy.txt”中。
with open('testfile.txt','r') as file1,open('copy.txt','w') as file2:	#打开两个文件
    file2.write(file1.read())		#将从“testfile.txt”中读取的内容写入到“copy.txt”中

文件的定位

获取当前读写位置

在读写文件的过程中,如果想知道当前文件位置指针的位置,可以通过调用tell()方法来获取。tell()方法返回文件的当前位置,即文件位置指针当前位置。

# 格式:
文件对象名.tell()

# 例:使用tell()方法获取文件当前的读写位置。
with open('testfile.txt','r') as file:	#以只读方式打开名为“testfile.txt”的文件
    line = file.read(8)		#读取前8个字节
    print(line)			#输出前8个字节
    p = file.tell()			#获取指针当前位置
    print('当前位置:',p)		#输出当前位置
    line = file.read(4)		#继续读取4个字节
    print(line)			#输出读取到的数据
    p = file.tell()			#获取指针当前位置
    print('当前位置:',p) 		#输出当前位置
定位到某个位置

如果在读写文件的过程中,需要从指定的位置开始读写操作,就可以使用seek()方法实现。seek()方法用于移动文件位置指针到指定位置

# 格式:
文件对象名.seek(offset[,whence])

# whence : 可选,默认值为0,表示起始点,即位移量的参考点,有三种取值,0代表“文件开始位置”,1代表“当前位置”,2代表“文件末尾位置”。
# offset : 表示偏移量,也就是需要偏移的字节数。


# 例子:创建名为“seek.txt“的文件,输入“This is a test!”并存放进文件中,读取单词“test”并输出到终端。
filename = input('请输入新建的文件名:')		#输入文件名
with open(filename,'w+') as file:			#新建文件并以读写方式打开
    file.write('This is a test!')			#将字符串输入到文件
    file.seek(10)					#指针移到从头开始的第10个字符处
    con = file.read(4)				#读取4个字符给con
    print(con)					#输出

提示:
以文本文件格式打开文件时,seek()方法中的whence参数取值只能是0,即只允许从文件开始位置计算偏移量。若想从当前位置或文件末尾位置计算偏移量,需要使用“b”模式(二进制格式)打开文件。

# 例子:读取“seek.txt”文件中倒数第2个字符。
with open('seek.txt','rb') as file:		#新建文件并以读写方式打开 open('seek.txt','r')
    file.seek(-2,2)				#将文件位置指针定位到倒数第2个字符处
    con = file.read(1)			#读取1个字符给con
    print(con)				#输出

文件与文件夹操作

os模块

Python标准库的os模块除了提供使用操作系统功能和访问文件系统的简便方法之外,还提供了大量文件级操作的方法。

方法功能说明
os.rename(src, dst)重命名(从src到dst)文件或目录,可以实现文件的移动,若目标文件已存在则抛出异常
os.remove(path)删除路径为path的文件,如果path是一个文件夹,则抛出异常
os.mkdir(path[,mode])创建目录,要求上级目录必须存在,参数mode为创建目录的权限,默认创建的目录权限为可读可写可执行
os.getcwd()返回当前工作目录
os.chdir(path)将path设为当前工作目录
os.listdir(path)返回path目录下的文件和目录列表
os.rmdir(path)删除path指定的空目录,如果目录非空,则抛出异常
os.removedirs(path)删除多级目录,目录中不能有文件
# 例子:
>>>import os				#导入os模块
>>>os.getcwd()				#显示当前工作目录
'E:\\Python代码\\第9章'
>>>os.mkdir('ostest')			#创建目录
>>>os.chdir('ostest')			#将“ostest”目录作为当前目录
>>>os.mkdir('mktest')			#在“ostest”目录中创建目录“mktest”
>>>f = open('1.txt','w')			#在当前工作目录下创建并打开“1.txt”文件
>>>f.close()				#关闭文件
>>>os.rename('1.txt','2.txt')			#重命名文件
>>>os.listdir('E:\\Python代码\\第9章\\ostest')	#查看文件和目录列表
['2.txt', 'mktest']
>>>os.rmdir('E:\\Python代码\\第9章\\ostest\\mktest')	#删除目录
>>>os.listdir('E:\\Python代码\\第9章\\ostest')		#再次查看文件和目录列表
['2.txt']
>>>os.remove('E:\\Python代码\\第9章\\ostest\\2.txt')	#删除文件
>>>os.listdir('E:\\Python代码\\第9章\\ostest')		#再次查看文件和目录列表
[]
# 例:批量修改文件名,在“ostest”目录下的文件名前加上编号,修改前和修改后的文件名如下图所示。
import os			#导入os模块
dir_list = os.listdir('ostest')		#调用listdir()方法返回“ostest”目录下的文件列表
i=1				#初始化i的值为1
os.chdir('ostest')			#将当前工作目录切换到“ostest”目录下
for name in dir_list:		#遍历列表
    print(name)			#输出原文件名
    new_name = str(i) + name	#在原文件名前加上数字进行编号
    i += 1				#i加1
    print(new_name)		#输出新文件名
    os.rename(name,new_name)	#重命名文件
os.path模块

os.path模块提供了大量用于路径判断、文件属性获取的方法。

方法功能说明
os.path.abspath(path)返回给定路径的绝对路径
os.path.split(path)将path分割成目录和文件名二元组返回
os.path.splitext(path)分离文件名与扩展名;默认返回(fname,fextension)元组,可做分片操作
os.path.exists(path)如果path存在,返回True;如果path不存在,返回False
os.path.getsize(path)返回path文件的大小(字节)
os.path.getatime(path)得到指定文件最后一次的访问时间
os.path.getctime(path)得到指定文件的创建时间
os.path.getmtime(path)得到指定文件最后一次的修改时间
# 例子:
>>>import os.path				#导入os.path模块
>>>os.path.abspath('ostest')			#查看绝对路径
'E:\\Python代码\\第9章\\ostest'
>>>os.path.split(' E:\\Python代码\\第9章\\ostest')	#分割目录和文件名
('E:\\Python代码\\第9章', 'ostest')
>>>os.path.splitext('9-1.py')			#分离文件名与扩展名
('9-1', '.py')
>>>os.path.exists('ostest')				#查看文件是否存在
True
>>>os.path.getsize('9-1.py')			#查看文件大小
290

知识库:
getatime()、getctime()和getmtime()方法分别用于获取文件的最近访问时间,创建时间和修改时间。不过返回值是浮点型秒数,可用time模块的gmtime()或localtime()方法换算。

# 例子:
>>>import os.path
>>>import time
>>>temp = time.localtime(os.path.getatime('testfile.txt'))
>>>print('testfile.txt被访问时间为:',time.strftime('%d %b %Y %H:%M:%S',temp))
testfile.txt被访问时间为:22 Jun 2018 11:22:12
shutil模块

shutil模块也提供了大量方法支持文件和文件夹操作。

方法功能说明
shutil.copy(src,dst)复制文件内容以及权限,如果目标文件已存在则抛出异常
shutil.copy2(src,dst)复制文件内容以及文件的所有状态信息,如果目标文件已存在则抛出异常
shutil.copyfile(src,dst)复制文件,不复制文件属性,如果目标文件已存在则直接覆盖
shutil.copytree(src,dst)递归复制文件内容及状态信息
shutil.rmtree(path)递归删除文件夹
shutil.move(src, dst)移动文件或递归移动文件夹,也可给文件和文件夹重命名
# 例子:
>>>import shutil				#导入shutil模块
>>>shutil.copy('testfile.txt','copytest.txt')		#复制文件内容以及权限
'copytest.txt'
>>>shutil.copytree('ostest','copytest')		#递归复制文件内容及状态信息
'copytest'
>>>shutil.rmtree('copytest')			#递归删除文件夹

异常

语法错误和异常

  1. 语法错误
    语法错误也称为解析错误,是初学者经常会遇到的问题。
a = 1
if a == 1 print("Yes")

"""
  File "<stdin>", line 1
    if a == 1 print("Yes")
              ^
SyntaxError: invalid syntax
"""
  1. 异常
    即使Python程序的语法是正确的,在运行时也有可能发生错误,这种在运行期间检测到的错误称为异常。大多数异常是不会被程序自动处理的,会以错误信息的形式进行展现。
print('2' + 2)

"""控制台
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: must be str,not int
>>>1/0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
"""

python中的异常

  1. TypeError
    当将不同类型的数据进行运算操作时,有时会引发TypeError(不同类型间的无效操作)异常。
birth = input('birth:')
if birth < 2000:
    print('00前')
else:
    print('00后')

"""控制台
birth:1998
Traceback (most recent call last):
  File "1.py", line 2, in <module>
    if birth < 2000:
TypeError: '<' not supported between instances of 'str' and 'int'
"""
  1. ZeroDivisionError
    当除数为零时,会引发ZeroDivisionError(除数为零)异常。
print(1/0)

"""控制台
Traceback (most recent call last):
  File "E:\Python代码\第10章\1.py", line 1, in <module>
    print(1/0)
ZeroDivisionError: division by zero
"""
  1. NameError
    当尝试访问一个未声明的变量时,会引发NameError(尝试访问一个不存在的变量)异常。
a = 1
c = a + b
print(c)

"""控制台
Traceback (most recent call last):
  File "E:\Python代码\第10章\1.py", line 2, in <module>
    c = a + b
NameError: name 'b' is not defined
"""
  1. SyntaxError
    解释器发现语法错误时,会引发SyntaxError(Python语法错误)异常。
list_1 = [1,2,3,4]
for i in list_1
    print(i)

"""控制台
File "E:\Python代码\第10章\1.py", line 2
    for i in list_1
             ^
SyntaxError: invalid syntax
"""
  1. IndentationError
    Python最具特色的就是依靠代码块的缩进来体现代码之间的逻辑关系,当缩进错误时,会引发IndentationError(缩进错误)异常。
list_1 = [1,2,3,4]
for i in list_1:
print(i) #没有缩进

"""控制台
File "E:\Python代码\第10章\1.py", line 3
    print(i)
       ^
IndentationError: expected an indented block
"""
  1. IndexError
    当使用序列中不存在的索引时,会引发IndexError(索引超出序列的范围)异常。
list_1 = [1,2,3,4]
print(list_1[4]) #索引超出范围

"""控制台
Traceback (most recent call last):
  File "E:\Python代码\第10章\1.py", line 2, in <module>
    print(list_1[4])
IndexError: list index out of range
"""
  1. KeyError
    当使用字典中不存在的时,会引发KeyError(字典中查找一个不存在的关键字)异常。
dict_1 = {'one':1,'two':2}
print(dict_1['one'])
print(dict_1['three']) #该字典中不存在的键

"""控制台
1
Traceback (most recent call last):
  File "E:\Python代码\第10章\1.py", line 3, in <module>
    print(dict_1['three'])
KeyError: 'three'
"""
  1. ValueError
    当传给函数的参数类型不正确时,会引发ValueError(传入无效参数)异常。
a = int('b')

"""控制台
Traceback (most recent call last):
  File "E:\Python代码\第10章\1.py", line 1, in <module>
    a = int('b')
ValueError: invalid literal for int() with base 10: 'b'
"""
  1. FileNotFoundError
    当试图用只读方式打开一个不存在的文件时,会引发FileNotFoundError (Python 3.2以前是IOError)异常。
file = open('1.txt')

"""控制台
Traceback (most recent call last):
  File "E:\Python代码\第10章\1.py", line 1, in <module>
    file = open('1.txt')
FileNotFoundError: [Errno 2] No such file or directory: '1.txt'
"""
  1. AttributeError
    当尝试访问未知的对象属性时,会引发AttributeError(尝试访问未知的对象属性)异常。
class Car():
    color = 'black'
car = Car()
print(car.color)
print(car.name)

"""控制台
black
Traceback (most recent call last):
  File "E:\Python代码\第10章\1.py", line 5, in <module>
    print(car.name)
AttributeError: 'Car' object has no attribute 'name'
"""

异常检测和处理

try-except
  1. 捕获单个异常:try-except语句用于检测和处理异常
    其最简单的语法格式如下:
try:
    #可能会引发异常的代码块
except Exception:
    #出现异常后执行的代码块
# 例子:
try:
    a = float(input('请输入被除数:'))
    b = float(input('请输入除数:'))
    c = a/b
    print('商为:',c)
except ZeroDivisionError:
    print('除数不能为0!')
  1. 针对不同异常设置多个except:处理多个异常的try-except语句
    其语法格式如下:
try:
    #可能会引发异常的代码块
except Exception1:
    #处理异常类型1的代码块
except Exception2:
    #处理异常类型2的代码块
except Exception3:
    #处理异常类型3的代码块
# 例子:
try:
    a = float(input('请输入被除数:'))
    b = float(input('请输入除数:'))
    c = a/b
    print('商为:',c)
except ZeroDivisionError:
    print('除数不能为0!')
except ValueError:
    print('被除数和除数应为数值类型!')
  1. 对多个异常统一处理:
    为减少代码量,Python允许将多个异常类型放到一个元组中,然后使用一个except子句同时捕捉多种异常,并且共用同一段异常处理代码。
# 例子:将上例的两个异常合并到一个except子句中。
try:
    a = float(input('请输入被除数:'))
    b = float(input('请输入除数:'))
    c = a/b
    print('商为:',c)
except (ZeroDivisionError,ValueError):
    print('捕获到异常!')

# 例子2:捕获异常的描述信息。
try:
    a = float(input('请输入被除数:'))
    b = float(input('请输入除数:'))
    c = a/b
    print('商为:',c)
except (ZeroDivisionError,ValueError) as r:
    print('捕获到异常:%s'%r)
  1. 捕获所以异常
    如果无法确定要对哪一类异常进行处理,只是希望在try语句块出现任何异常时,都给用户一个提示信息,那么可以在except子句中不指明异常类型
# 例:捕获所有异常。
try:
    a = float(input('请输入被除数:'))
    b = float(input('请输入除数:'))
    c = a/b
    print('商为:',c)
except:
    print('出错啦!')
# 例:使用Exception关键字代替所有异常。
try:
    a = float(input('请输入被除数:'))
    b = float(input('请输入除数:'))
    c = a/b
    print('商为:',c)
except Exception as r:
    print('捕获到异常:%s'%r)
try-except-else

try-except语句还有一个可选的else子句,如要使用该子句,必须将其放在所有except子句之后。该子句将在try子句没有发生任何异常时执行。
该结构的语法格式如下:

try:
    #可能会引发异常的代码块
except Exception [as reason]:
    #出现异常后执行的代码块
else:
    #如果try子句中的代码没有引发异常,则执行该代码块
# 例:以只读方式打开文件,并统计文件中文本的行数,如果文件不存在则给出提示信息。
arg = '1.txt'
try:
    f = open(arg, 'r')
except FileNotFoundError:
    print(arg,'文件不存在')
else:
    print(arg, '文件有', len(f.readlines()), '行')
    f.close()

提示:
建议在try子句中只放真的有可能会引发异常的代码,将其余代码放在else子句中。

try-except-finally

在程序中,类似上述情况,无论是否捕获到异常,都需要执行一些终止行为(如关闭文件),Python引入了finally子句来扩展try,
该结构的语法格式如下:

try:
    #可能会引发异常的代码块
except Exception [as reason]:
    #出现异常后执行的代码块
finally:
    #无论try子句中的代码有没有引发异常,都会执行的代码块
# 例子:
try:
    f = open('1.txt')
    print(a)
    f.close()
except:
    print('出错啦!')

# 例子2:修改上述代码,使其无论是否捕获到异常,都会执行关闭文件的操作。
try:
    f = open('1.txt')
    print(a)
except:
    print('出错啦!')
finally:
    f.close()
'''
运行程序时,如果“1.txt”文件不存在,就会在finally子句中关闭文件时引发异常。
'''

提示:
异常处理结构不是万能的,并不是采用了异常处理结构就万事大吉了,finally子句中的代码也可能会引发异常。

同时包含多个except、else和finally子句

Python异常处理结构中可以同时包含多个except子句、else子句和finally子句
其语法格式如下:

try:
    #可能会引发异常的代码块
except Exception1:
    #处理异常类型1的代码块
except Exception2:
    #处理异常类型2的代码块else:
    #如果try子句中的代码没有引发异常,则执行该代码块
finally:
    #无论try子句中的代码有没有引发异常,都会执行的代码块


# 1)在上述语句中,异常处理结果必须以“try”→“except”→“else”→“finally”的顺序出现,即所有的except必须在else和finally之前,else必须在finally之前,否则会出现语法错误。

# (2)else和finally都是可选的。

# (3)else的存在必须以except语句为前提。就是说,如果在没有except语句的try语句中使用else语句会引发语法错误。
# 例子:同时包含多个except、else和finally子句的异常处理。
try:
    a = float(input('请输入被除数:'))
    b = float(input('请输入除数:'))
    c = a/b
    print('商为:',c)
except ZeroDivisionError:
    print('除数不能为0!')
except ValueError:
    print('被除数和除数应为数值类型!')
except:
    print('其他错误!')
else:
    print('运行没有错误!')
finally:
    print('运行结束!')

抛出异常

raise语句
  1. 使用异常名引发异常
    使用异常名引发异常的基本语法格式如下:
raise 异常名称
# 当raise语句指定异常名时,会创建该类的实例对象,然后引发异常。
# 例子:
raise NameError

"""控制台
Traceback (most recent call last):
  File "E:\Python代码\第10章\1.py", line 1, in <module>
    raise NameError
NameError
"""
  1. 使用异常类的实例引发异常
    使用异常类的实例引发异常的基本语法格式如下:
raise 异常名称('异常描述')
# 通过显式地创建异常类的实例,直接使用该实例对象来引发异常,同时还能给异常类指定描述信息。
# 例子:
raise NameError('命名错误')

"""控制台
Traceback (most recent call last):
  File "E:\Python代码\第10章\1.py", line 1, in <module>
    raise NameError('命名错误')
NameError: 命名错误
"""
# : raise语句使用实例。

#定义输出矩形图形的函数
def boxPrint(s, w, h):
    if len(s) != 1:				#当输入的字符不为单个字符时抛出异常
        raise Exception('输入的符号必须是单个字符!')
    if w <= 2: 				#当输入的宽度小于等于2时抛出异常
        raise Exception('宽必须大于2!')
    if h <= 2: 				#当输入的高度小于等于2时抛出异常
        raise Exception('高必须大于2!')
#输出矩形图形
    print(s * w)
    for i in range(h - 2):
        print(s + (' ' * (w - 2)) + s)
    print(s * w)
#给s, w, h赋不同的值
for s, w, h in (('*', 3, 3), ('#', 4, 4), ('$$', 3, 3), ('@', 1, 3),('+', 3, 2)):
#异常处理
    try:
        boxPrint(s, w, h)
    except Exception as err:
        print('发生了一个异常: ' + str(err))
  1. 传递异常
    捕获到了异常,但是又想重新引发它(传递异常),可以使用不带参数的raise语句。
try:
    raise NameError('命名错误')
except NameError:
    print('出现了一个异常!')
    raise

"""控制台
出现了一个异常!
Traceback (most recent call last):
  File "E:\Python代码\第10章\1.py", line 2, in <module>
    raise NameError('命名错误')
NameError: 命名错误
"""
assert语句

assert语句又称为断言,断言表示为一些逻辑表达式,程序员相信,在程序中的某个特定点该表达式值为真,如果为假,就会触发AssertionError异常。
assert语句的基本语法格式如下:

assert 逻辑表达式 [,参数]

# assert后面紧跟逻辑表达式,参数为一个字符串,当表达式的值为假时,作为异常类的描述信息使用。逻辑上等同于:
'''
if not 逻辑表达式:
    raise AssertionError(参数)
'''
# 例子:
a = 3
assert a >5, 'a的值应大于5'

"""控制台
Traceback (most recent call last):
  File "E:\Python代码\第10章\1.py", line 2, in <module>
    assert a >5, 'a的值应大于5'
AssertionError: a的值应大于5
"""
# 例: assert语句使用实例。

while True:
    try:
        score=int(input("请输入百分制成绩:"))
#断言score是在0~100分之间,如果不是抛出异常
        assert score>=0 and score<=100,'分数必须在1~100之间'
        if score>=90:
            print("优")
        elif score>=80: 
            print("良")
        elif score>=70:
            print("中")
        elif score>=60:
            print("及格")
        else:
            print("不及格")
    except Exception as r:
        print('发生异常:',r)
        break		#跳出循环

用户自定义异常

Python的异常分为两种:

  • 一种是内建异常,就是系统内置的异常,在某些错误出现时自动触发;
  • 另一种是用户自定义异常,就是用户根据自己的需求设置的异常。
    Exception类是所有异常的基类,因此,用户自定义异常类需从Exception类继承。
# 例:用户注册账户时,输入的性别只能是“男”或“女”,要求自定义异常,当输入数据不是“男”或“女”时抛出异常。
#用户自定义异常类
class SexException(Exception):
    def __init__(self,msg,value):
        self.msg = msg
        self.value = value
#定义函数,用于输入性别并判断是否输入的是“男”或“女”
def f():
    sex = input('请输入性别:')
    if sex!='男' and sex!='女':
        raise SexException('性别只能输入男或者女',sex)		#抛出异常
#异常处理
try:
    f()
except Exception as ex:
    print('错误信息是:%s,输入的性别是:%s'%(ex.msg,ex.value))

GUI编程

tkinter和Python编程

tkinter简介
  • tkinter是Python的标准GUI库。
  • tkinter的优点是简单易用,与Python结合度好。
  • tkinter在Python 3.x下默认集成,不需要额外安装。因此,想要使用tkinter进行GUI编程,可直接使用import语句导入tkinter模块。
import tkinter
tkinter的使用

创建一个GUI应用程序需要以下5个主要步骤:

  1. 导入tkinter模块(import tkinter)
  2. 创建一个顶层窗口对象(调用Tk()函数),用于容纳整个GUI应用
  3. 在顶层窗口对象上构建所有的GUI控件
  4. 通过底层应用代码将这些GUI控件连接起来
  5. 进入主事件循环(调用mainloop()函数)
# 例:第一个tkinter实例——创建一个窗口用于输出"Hello world"。
import tkinter					#导入tkinter模块
top = tkinter.Tk()				#创建一个顶层窗口对象
label = tkinter.Label(top,text='Hello World',fg='red')#添加一个Label控件,用于显示文本
label.pack()					#调用Label控件的pack()方法
top.mainloop()					#进入主事件循环

tkinter常用控件

在GUI编程中,顶层窗口对象包含组成GUI应用程序的所有小窗口对象,它们可能是文字标签、按钮、列表框等,这些独立的GUI组件称为控件

控制描述
Button按钮控件,在程序中显示按钮
Canvas画布控件,显示图形元素,如线条、椭圆、矩形等
Checkbutton多选框控件,用于在程序中提供多项选择框
Entry输入控件,用于显示简单的文本内容
Frame框架控件,在屏幕上显示一个矩形区域,多用作容器
Label标签控件,可以显示文本和图像
LabelFrameFrame的进化版,标签和框架的组合
Listbox列表框控件,用来显示一个字符串列表给用户
Menu菜单控件,显示菜单栏、下拉菜单和弹出菜单
Menubutton菜单按钮控件,用于显示菜单项
Message消息控件,用来显示多行文本,与Label类似
PanedWindow窗口布局管理插件,可以包含一个或多个子控件
Radiobutton单选按钮控件,显示一个单选的按钮状态
Scale线性滑块控件,根据已设定的起始值和终止值,给出当前设定的精确值
Scrollbar滚动条控件,当内容超过可视化区域时使用,如列表框
SpinboxEntry和Button的组合,允许对值进行调整
Text文本控件,用于显示多行文本
Toplevel容器控件,用来提供一个单独的对话框,和Frame类似
窗口

窗口也称为框架Frame),是屏幕上的一块矩形区域,多用来作为容器布局窗体。
窗口中可包含标签、菜单、按钮等其他控件,其运行之后可移动和缩放。

属性描述
title设置窗口标题
geometry设置窗口大小
resizable设置窗口是否可以变化长和宽
# 例:创建一个300×200的窗口,其标题为“金企鹅”,运行后该窗口宽不可变,高可变。
import tkinter						#导入tkinter库
window = tkinter.Tk()					#创建tkinter对象
window.title("金企鹅")					#设置标题
window.geometry("300x200")				#设置窗口大小,注意是字母x
window.resizable(width=False, height=True)		#宽不可变,高可变,默认为True
window.mainloop()					#进入主事件循环
Label控件

Label控件是用于在界面上输出描述信息的标签,可以显示文本和图像。

属性描述
text要显示的文本
bg背景颜色
fg前背景
bd外围3D边界的宽度
font字体
width控件宽度
height控件高度
relief边框样式
# 例:创建一个200×100的窗口,其标题为“金企鹅”,在窗口中创建一个标签,用于显示“金企鹅联合出版中心”,并设置其字体、颜色、宽度和高度。
import tkinter				#导入tkinter库
window = tkinter.Tk()			#创建tkinter对象
window.title("金企鹅")			#设置标题
window.geometry("200x100")		#设置窗口大小,注意是字母x
#创建标签,text设置文本,bg设置背景色,fg设置前景色,font设置字体,width设置宽,height设置高
label1 = tkinter.Label(window, text="金企鹅联合出版中心", bg="white", fg="blue", font=("宋体"), width=20, height=3)
label1.pack()				#显示Label
window.mainloop()			#进入主事件循环
Button控件

通过Button控件可以方便地与用户进行交互。Button控件有一个command属性,用于指定一个函数或方法,当用户单击按钮时,tkinter就会自动调用该函数或方法。

# 例:编写程序实现通过按下按钮来执行指定操作(改变标签的内容)
import tkinter as tk				#导入tkinter模块重命名为tk
#定义函数,用于实现改变标签的内容
def btnHelloClicked():
    labelHello.config(text = "Hello tkinter!")
top = tk.Tk()					#创建tkinter对象
top.geometry("200x150")				#设置窗口大小,注意是字母x
top.title("Button Test")				#设置窗口标题
#创建原始标签
labelHello = tk.Label(top, text = "Press the button...", height = 5, width = 20, fg = "blue")
labelHello.pack()					#显示标签
#创建按钮,显示“Hello”,单击按钮调用btnHelloClicked函数
btn = tk.Button(top, text = "Hello", command = btnHelloClicked)
btn.pack()					#显示按钮
top.mainloop()					#进入主事件循环
Entry控件

Entry控件就是输入框,用来输入单行内容,可以方便地向程序传递用户参数。获取输入框的内容可以使用Entry控件的get()方法。

# :编写摄氏度转华氏度的小程序,要求从输入框输入摄氏度的值,单击计算按钮后得到华氏度的值。计算公式:F = 1.8×C+32。

import tkinter as tk	#导入并重命名tkinter模块
#定义函数用于读取Entry控件的内容并将计算结果进行输出
def btnHelloClicked():
    cd = float(entryCd.get())		#读取Entry控件的内容
    labelHello.config(text = "%.2f°C = %.2f°F" %(cd, cd*1.8+32))
top = tk.Tk()			#创建tkinter对象
top.title("Entry Test")		#设置窗口标题
#创建标签
labelHello = tk.Label(top, text = "摄氏度转华氏度", height = 5, width = 20, fg = "blue")
labelHello.pack()			#显示标签
entryCd = tk.Entry(top, text = "0")	#创建输入框
entryCd.pack()			#显示输入框
#创建按钮
btnCal = tk.Button(top, text = "计算", command = btnHelloClicked)
btnCal.pack()			#显示按钮
top.mainloop()			#进入主事件循环
Radiobutton和Checkbutton控件

Radiobutton和Checkbutton控件分别用于实现选项的单选和复选功能。

属性描述
variable单选框索引变量,通过变量的值确定哪个单选框被选中,一组单选框使用同一个索引变量
value单选框选中时变量的值
command单选框选中时执行的命令(函数)
属性描述
variable复选框索引变量,通过变量的值确定哪些复选框被选中;每个复选框使用不同的变量,使复选框之间相互独立
onvalue复选框选中(有效)时变量的值
offvalue复选框未选中(无效)时变量的值
command复选框选中时执行的命令(函数)
# 例:编写程序,实现通过单选框和复选框设置文字样式的功能。
import tkinter as tk				#导入tkinter模块重命名为tk
#定义函数用于修改标签中文字的颜色
def colorChecked():
    labelHello.config(fg = color.get())
#定义函数用于修改标签中文字的字体
def typeChecked():
    textType = typeBlod.get() + typeItalic.get()		#两个复选框的值相加
    if textType == 1:				#单选typeBlod复选框
        labelHello.config(font = ("Arial", 12, "bold"))
    elif textType == 2:				#单选typeItalic复选框
        labelHello.config(font = ("Arial", 12, "italic"))
    elif textType == 3:				#同时选中两个复选框
        labelHello.config(font = ("Arial", 12, "bold italic"))
    else:						#两个都不选
        labelHello.config(font = ("Arial", 12))

top = tk.Tk()						#创建tkinter对象
top.title("Radio & Check Test")				#设置窗口标题
#创建标签
labelHello = tk.Label(top, text = "Check the format of text.", height = 3, font=("Arial", 12))
labelHello.pack()						#显示标签
color = tk.StringVar()					#获取单选框输入
#创建三个单选框并显示
tk.Radiobutton(top, text = "Red", variable = color, value = "red", command = colorChecked).pack()
tk.Radiobutton(top, text = "Blue", variable = color, value = "blue", command = colorChecked).pack()
tk.Radiobutton(top, text = "Green", variable = color, value = "green", command = colorChecked).pack()
#获取复选框输入
typeBlod = tk.IntVar()
typeItalic = tk.IntVar()
#创建2个复选框
tk.Checkbutton(top, text = "Blod", variable = typeBlod, onvalue = 1, offvalue = 0, command = typeChecked).pack()
tk.Checkbutton(top, text = "Italic", variable = typeItalic, onvalue = 2, offvalue = 0, command = typeChecked).pack()
top.mainloop()						#进入主事件循环

提示:
可以使用tkinter.StringVar()创建与特定控件关联的字符串变量,使用tkinter.IntVar()创建与特定控件关联的整型变量。

Menu控件

tkinter提供了Menu控件,用于实现顶级菜单、下拉菜单和弹出菜单。

函数名称说明
menu.add_cascade()添加子选项
menu.add_command()添加命令(label参数为显示内容)
menu.add_separator()添加分隔线
menu.add_checkbutton()添加确认按钮
  1. 顶级菜单
    创建一个顶级菜单,需要先创建一个菜单实例,然后使用add()方法将命令添加进去。
# 例:创建顶级菜单实例。
import tkinter				#导入tkinter库
#定义函数用于显示信息
def callback():
    print('单击了“显示”菜单!')
window = tkinter.Tk()			#创建tkinter对象
window.title("标题")			#设置标题
window.geometry("200x100")		#设置窗口大小
menubar = tkinter.Menu(window)		#创建一个顶级菜单窗口
#给菜单实例增加菜单项
menubar.add_command(label='显示', command = callback)
menubar.add_command(label='退出', command = window.quit)
window.config(menu = menubar)		#显示菜单
window.mainloop()			#进入主事件循环
  1. 下拉菜单
    创建一个下拉菜单,方法同创建顶级菜单类似,最主要的区别是下拉菜单需要添加到主菜单上。
# 例:创建下拉菜单实例。

import tkinter			
window = tkinter.Tk()		
window.title("标题")		
window.geometry("200x100")	
#创建一个顶级菜单实例
menubar = tkinter.Menu(window)
#为每个子菜单实例添加菜单项
#创建文件菜单项,并添加子菜单
fmenu = tkinter.Menu(menubar)
for each in ['新建','打开','保存','另存为']:
    fmenu .add_command(label = each)


#创建视图菜单项,并添加子菜单
vmenu = tkinter.Menu(menubar)
for each in ['复制','粘贴','剪切']:
    vmenu.add_command(label = each)
#创建编辑菜单项,并添加子菜单
emenu = tkinter.Menu(menubar)
for each in ['默认视图','新式视图']:
    emenu.add_command(label = each)
#创建关于菜单项,添加子菜单
amenu = tkinter.Menu(menubar)
for each in ['版权信息','联系我们']:
    amenu.add_command(label = each)


#为顶级菜单实例添加菜单,并绑定相应的子菜单实例
menubar.add_cascade(label='文件',menu=fmenu)
menubar.add_cascade(label='视图',menu=vmenu)
menubar.add_cascade(label='编辑',menu=emenu)
menubar.add_cascade(label='关于',menu=amenu)
window.config(menu = menubar)	#显示菜单
window.mainloop()		#进入主事件循环
  1. 弹出菜单
    创建一个弹出菜单的方法也是类似的,不过需要使用post()方法将其显示出来。
# 例:创建弹出菜单实例。
from tkinter import *	
root = Tk()			
#定义函数用于输出提示信息
def hello():
    print( "选择了菜单!")
root.geometry("200x100")			
#创建一个顶级菜单实例
menu = Menu(root)
menu.add_command(label="显示", command=hello)
menu.add_command(label="退出", command=root.quit)


#弹出菜单
frame = Frame(root, width=512, height=512)
frame.pack()
#定义函数,调用post()方法显示
def popup(event):
    menu.post(event.x_root, event.y_root)
#绑定鼠标右键
frame.bind("<Button-3>", popup)
root.config(menu = menu)		
root.mainloop()

事件绑定

事件序列
  • 一个tkinter应用程序的大部分时间花费在事件循环上(通过mainloop()方法进入)。
  • 事件可以有多种来源,包括用户触发的鼠标、键盘操作或是系统事件。
  • tkinter提供了强大的事件处理机制,对于每个控件来说,可以通过bind()方法将函数或方法绑定到具体的事件上,
    其语法格式如下:
控件对象名.bind(event, handler)

# event : 是tkinter已经定义好的事件(通过事件序列机制定义)。
# handler : 是一个处理函数或方法。
# 例:捕获鼠标点击事件实例。
from tkinter import *				#导入tkinter库中所有内容
root = Tk()					#创建tkinter对象
#定义函数,用于输出鼠标单击的坐标
def callback(event):
    print ("clicked at", event.x, event.y)
frame = Frame(root, width=200, height=100)	#创建窗体
frame.bind("<Button-1>", callback)		#绑定鼠标左键
frame.pack()					#显示窗体
root.mainloop()					#进入主事件循环
  1. tkinter使用一种称为事件序列的机制来允许用户定义事件,事件序列以字符串的形式表示,
    其语法格式如下:
<modifier-type-detail>

说明:
(1)事件序列必须用尖括号括起来;
(2type字段是最重要的,它通常用于描述事件类型,如鼠标单击、键盘输入等;
(3)modifier字段是可选的,它通常用于描述组合键,如Ctrl、Shift等;
(4)detail字段也是可选的,它通常用于描述具体的按键,如Button-1 表示单击鼠标左键。
  1. type字段常用的关键字及含义:
    | 关键字 | 含义 |
    | ------------- | ---------------------------------------- |
    | Button | 鼠标单击事件,detail部分指定具体哪个按键:鼠标左键,鼠标中键,鼠标右键。鼠标的位置x和y会被event对象传给handler |
    | ButtonRelease | 鼠标释放事件,在大多数情况下,比Button要更好用,因为如果当用户不小心按下鼠标,用户可以将鼠标移出控件再释放鼠标,从而避免不小心触发事件 |
    | Configure | 控件大小改变事件,新的控件大小会存储在event对象中的width和height属性中传递 |
    | Enter | 鼠标移入控件事件 |
    | FocusIn | 获得焦点事件 |
    | FocusOut | 失去焦点事件 |
    | Leave | 鼠标移出控件事件 |
    | KeyPress | 键盘按下事件,detail可指定具体的按键,例如,表示当大写字母H被按下时触发该事件,KeyPress也可以简写成Key |
    | Motion | 鼠标移动事件,鼠标在控件内移动的整个过程均触发该事件 |

  2. modifier字段常用的关键字及含义
    | 关键字 | 含义 |
    | ------- | ---------------------------------------- |
    | Alt | 当按下Alt键时 |
    | Any | 表示任何类型的按键被按下时,例如,表示当用户按下任意键时触发事件 |
    | Control | 当按下Ctrl键时 |
    | Double | 当后续事件被连续触发两次时,例如,表示当用户双击鼠标左键时触发事件 |
    | Lock | 当打开大写字母锁定键时 |
    | Shift | 当按下Shift键时 |
    | Triple | 跟Double类似,当后续事件被连续触发三次时 |

事件对象

当tkinter调用预先定义的函数时,会将事件对象(作为参数)传递给函数,事件对象的属性及含义如下表所示。

属性含义
widget产生事件的控件
x, y当前鼠标的位置(相对于窗口左上角,单位为像素)
x_root, y_root当前鼠标的位置(相对于屏幕左上角,单位为像素)
char字符代码(仅限键盘事件),作为字符串
keysym关键符号(仅限键盘事件)
keycode关键代码(仅限键盘事件)
num按钮数字(仅限鼠标按钮事件)
width, height控件的新尺寸(Configure事件专属)
type事件类型
# 例:事件绑定实例。
import tkinter		#导入tkinter库
window = tkinter.Tk()	#创建tkinter对象
window.title("标题")	#设置标题
window.geometry("200x100")	#设置窗口大小
#鼠标单击绑定事件
def func(event):
    print("单击!")
window.bind("<Button-1>",func)
#鼠标双击绑定事件
def func1(event):
    print("双击!")
window.bind("<Double-Button-1>",func1)


#鼠标移入绑定事件
def func2(event):
    print("鼠标移入!")
window.bind("<Enter>",func2)
#实现拖拽功能
def func3(event):
    x=str(event.x_root)
    y=str(event.y_root)
    window.geometry("200x100+"+x+"+"+y)
window.bind("<B1-Motion>",func3)
window.mainloop()

布局管理器

pack布局

pack布局是按添加的顺序排列控件,即向容器中添加控件,第一个添加的控件在最上方,然后依次向下排列。

# 例:pack布局实例。
from tkinter import *		#导入tkinter库中所有内容
root = Tk()			#创建tkinter对象
#创建三个标签
Label(root, text = 'pack1', bg = 'red').pack()
Label(root, text = 'pack2', bg = 'blue').pack()
Label(root, text = 'pack3', bg = 'green').pack()
root.mainloop()			#进入主事件循环

pack布局的常用属性

属性名含义取值说明
fill设置控件是否向水平或垂直方向填充X(水平方向填充)、Y(垂直方向填充)、BOTH(水平和垂直)、NONE(不填充)
expand设置控件是否展开,当值为YES时,side选项无效,控件显示在父容器中心位置;若fill选项为BOTH,则填充父控件的剩余空间;默认为不展开expand = YES expand = NO
side设置控件的对齐方式LEFT(左)、TOP(上)、RIGHT(右)、BOTTOM(下)
ipadx ipady设置x方向(或者y方向)内部间隙(与子控件之间的间隔)可设置数值(非负整数,单位为像素),默认是0
padx pady设置x方向(或者y方向)外部间隙(与之并列的控件之间的间隔)可设置数值(非负整数,单位为像素),默认是0
anchor锚选项,当可用空间大于所需求的尺寸时,决定控件被放置于容器的位置N,E,S,W,NW,NE,SW,SE,CENTER(默认值为CENTER),表示八个方向以及中心

提示:
pack布局适用于少量控件的排列,当界面复杂度增加时,要实现某种布局效果,需要分层来实现。

# 例:分层实现较复杂布局。
from tkinter import *		
root = Tk()		
root.title("Pack - Example")		
#使用Frame增加一层容器
fm1 = Frame(root)
#创建3个按钮,从上到下排列
Button(fm1, text='Top').pack(side=TOP, anchor=W, fill=X)
Button(fm1, text='Center').pack(side=TOP, anchor=W, fill=X)
Button(fm1, text='Bottom').pack(side=TOP, anchor=W, fill=X)
fm1.pack(side=LEFT, fill=Y)


#使用Frame再增加一层容器
fm2 = Frame(root)
#创建3个按钮,从左到右排列
Button(fm2, text='Left').pack(side=LEFT)
Button(fm2, text='This is the Center button').pack(side=LEFT)
Button(fm2, text='Right').pack(side=LEFT) 
fm2.pack(side=LEFT, padx=10)
root.mainloop()
grid布局

grid布局又称为网格布局,是tkinter布局管理器中最灵活多变的布局方法。由于大多数程序界面都是矩形的,我们可以将它划分为由行和列组成的网格,然后根据行号和列号,将控件放置于网格之中。

属性名含义取值说明
row,columnrow为行号,column为列号,设置控件放置的位置(第几行第几列)row和column的序号都从0开始
sticky设置控件在网格中的对齐方式(类似于pack布局中的锚选项)N,E,S,W,NW,NE,SW,SE,CENTER
rowspan,columnspan控件所跨越的行数或列数取值为跨越占用的行数或列数
ipadx,ipady,padx,pady控件的内部和外部间隔距离与pack的该属性用法相同
# 例:grid布局实例。
from tkinter import *	#导入tkinter库中所有内容
root = Tk()		#创建tkinter对象
colours = ['red','green','orange','white','yellow','blue']	#定义颜色列表
r = 0
#循环创建标签和不同颜色的输入框
for c in colours:
    Label(root,text=c, relief=RIDGE,width=15).grid(row=r,column=0)
    Entry(root,bg=c, relief=SUNKEN,width=10).grid(row=r,column=1)
    r = r + 1
root.mainloop()		#进入主事件循环
place布局

place布局使用控件坐标来放置控件的位置。

属性名含义取值说明
x,y控件左上角的x,y坐标(绝对位置)整数,默认值为0,单位像素
relx,rely控件相对于父容器的x,y坐标(相对位置)0~1之间浮点数,0.0表示左边缘(或上边缘),1.0表示右边缘(或下边缘)
width,height控件的宽度和高度非负整数,单位像素
relwidth,relheight控件相对于父容器的宽度和高度与relx和rely取值相似
anchor锚选项同pack布局
bordermode如果设置为INSIDE,不包括边框;如果是OUTSIDE,包括边框INSIDE,OUTSIDE(默认值INSIDE)
# 例:place布局实例。
from tkinter import *		#导入tkinter库中所有内容
root = Tk()			#创建tkinter对象
root.geometry("200x100")	#设置窗口大小
la = Label(root,text = 'hello Place a')		#创建标签la
la.place(x = 0,y = 0,anchor = NW)		#使用绝对坐标将Label放置到(0,0)位置上
lb = Label(root,text = 'hello Place b')		#创建标签lb
lb.place(relx = 0.5,rely = 0.5,anchor = CENTER)	#使用相对坐标将标签放置到窗口中央
root.mainloop()					#进入主事件循环

提示:
(1)在同一个主窗口中不要混用这3种布局管理器。
(2)不推荐使用place布局,因为在不同分辨率下,界面往往有较大差异。

标准对话框

messagebox模块

messagebox模块用于显示一个模式对话框,其中包含一个系统图标、一组按钮和一个简短的特定于应用程序的消息,如状态或错误信息。

  • messagebox模块:
    • askokcancel()
    • askguestion()
    • askretrycancel()
    • askesno()
    • showerror()
    • showwarning()
# 例:messagebox模块实例。
import tkinter as tk				#导入tkinter模块并命名为tk
from tkinter import messagebox as msgbox	#导入tkinter. messagebox模块并命名
#定义各个函数用于相应按钮事件
def btn1_clicked():
    msgbox.showinfo("Info", " showinfo测试!")
def btn2_clicked():
    msgbox.showwarning("Warning", " showwarning测试!")
def btn3_clicked():
    msgbox.showerror("Error", "showerror测试!")
def btn4_clicked():
    msgbox.askquestion("Question", "askquestion测试!")
def btn5_clicked():
    msgbox.askokcancel("OkCancel", "askokcancel测试!")
def btn6_clicked(): 
    msgbox.askyesno("YesNo", "askyesno测试!") 
def btn7_clicked():
    msgbox.askretrycancel("Retry", "askretrycancel测试!")

top = tk.Tk()					#创建tkinter对象
top.title("MsgBox Test")				#设置标题
#创建按钮用于触发各个对话框函数
btn1 = tk.Button(top, text = "showinfo", command = btn1_clicked)
btn1.pack(fill = tk.X)
btn2 = tk.Button(top, text = "showwarning", command = btn2_clicked)
btn2.pack(fill = tk.X)
btn3 = tk.Button(top, text = "showerror", command = btn3_clicked)
btn3.pack(fill = tk.X)
btn4 = tk.Button(top, text = "askquestion", command = btn4_clicked)
btn4.pack(fill = tk.X)
btn5 = tk.Button(top, text = "askokcancel", command = btn5_clicked)
btn5.pack(fill = tk.X)
btn6 = tk.Button(top, text = "askyesno", command = btn6_clicked)
btn6.pack(fill = tk.X)
btn7 = tk.Button(top, text = "askretrycancel", command = btn7_clicked)
btn7.pack(fill = tk.X)
top.mainloop()					#进入主事件循环
filedialog模块

filedialog模块用于打开文件对话框,该模块提供了2个函数:

  • askopenfilename()函数用于打开“打开”对话框
  • asksaveasfilename()函数用于打开“另存为”对话框
# 例:filedialog模块实例。
import tkinter.filedialog			#导入tkinter.filedialog模块
from tkinter import *			#导入tkinter模块
root = Tk()				#创建tkinter对象
#定义函数用于响应按钮事件
def callback():
     fileName = filedialog.askopenfilename()	#打开“打开”对话框
     print(fileName)				#输出文件名
#创建按钮用于触发事件
Button(root,text='打开文件',command=callback).pack()
root.mainloop()				#进入主事件循环
colorchoose模块

colorchooser模块用于打开颜色选择对话框,由askcolor()函数实现。

# 例:colorchooser模块实例。
import tkinter.colorchooser		#导入tkinter.colorchooser模块
from tkinter import *		#导入tkinter模块
root = Tk()			#创建tkinter对象
#定义函数用于相应按钮事件
def callback():
     fileName = colorchooser.askcolor()	#打开颜色选择对话框
     print(fileName)				#输出颜色信息
#创建按钮
Button(root,text="选择颜色",command=callback).pack()
root.mainloop()				#进入主事件循环

网络爬虫

概述

  • 网络爬虫(Web Spider)又称网络蜘蛛或网络机器人,是一段用来实现自动采集网站数据的程序。
  • 网络爬虫不仅能够为搜索引擎采集网络信息,而且还可以作为定向信息采集器,定向采集某些网站中的特定信息。
  • 对于定向信息的爬取,网络爬虫主要采取数据抓取、数据解析、数据入库的操作流程。
  1. 数据抓取:发送构造的HTTP请求,获得包含所需数据的HTTP响应;
  2. 数据解析:对HTTP响应的原始数据进行分析、清洗,以提取出所需要的数据;
  3. 数据入库:将数据进一步保存到数据库(或文本文件)中,用于构建知识库。
|爬虫客户端|    |目标网站|      |数据库|
     |              |             |
     |(1)发送HTTP请求|             |
     |------------->|             |
     |(2)获取响应内容|             |
     |<-------------|             |
     |     (3)解析、|清洗、入库    |
     |-------------|------------->|

Python提供了许多与网络爬虫相关的库。其中,在数据抓取方面requests;在数据解析方面包括re(正则表达式),beautifulsoup4。

数据抓取

requests库概述

requests库提供了很多功能特性,几乎涵盖了所有Web服务的需求,包括URL获取、HTTP长连接和连接缓存、HTTP会话、浏览器式的SSL验证、身份认证、Cookie会话、文件分块上传、流下载、HTTP(S)代理功能、连接超时处理等。

由于requests库是第三方库,因此,需要通过pip3指令进行安装,pip3安装命令如下:

C:\>pip3 install requests

安装完requests库后,在Python交互模式下输入导入requests库的语句:

>>>import requests

如果没有提示错误,则说明安装成功。

使用requests库

网络爬虫工作流程的第一步是数据的抓取,也就是使用requests库实现发送HTTP请求获取HTTP响应的内容

  1. 发送HTTP请求
    requests库提供了几乎所有的HTTP请求方法:
函数描述
get(url[,timeout = n])对应于HTTP的GET方法,请求指定的页面信息,并返回实体主体;是获取网页最常用的方法,可通过timeout = n设置每次请求超时时间为n秒
head(url)对应于HTTP的HEAD方法,类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头
post(url,data = {‘key’:‘value’})对应于HTTP的POST方法,向指定资源提交数据,并处理请求(如提交表单或者上传文件);其中字典用于传递客户数据
delete(url)对应于HTTP的DELETE方法,请求服务器删除指定的页面
options(url)对应于HTTP的OPTIONS方法,允许客户端查看服务器的性能
put(url,data = {‘key’:‘value’})对应于HTTP的PUT方法,从客户端向服务器传送的数据取代指定的文档内容。其中字典用于传递客户数据

调用get()函数是获取网页最常用的方式,在调用requests.get()函数后,返回的网页内容会保存为一个Response对象。

>>>import requests				#导入requests库
>>>r = requests.get('http://www.baidu.com')	#使用get函数打开百度链接
>>>type(r)					#查看返回值r的类型
<class 'requests.models.Response'>

有时我们需要在URL中传递参数。

# 在采集百度搜索结果时,需要传递wd参数(搜索词)。requests允许使用params关键字参数,以一个字符串字典来提供这些参数。
>>>import requests				#导入requests库
>>>payload = {'wd': 'Python'}			#定义字典
>>>r = requests.get("http://www.baidu.com/s", params=payload)	#传入URL参数
>>>r.url							#输出URL的值
'http://www.baidu.com/s?wd=Python'

# 用浏览器打开被编码的URL得到百度搜索关键字“Python”的结果。
  1. 获取HTTP响应的内容
    和浏览器的交互过程一样,requests.get()代表发送HTTP请求的过程,它返回的Response对象代表HTTP响应。我们可以通过Response对象的不同属性来获取不同内容,
    其语法格式如下:
对象名.属性名

Response对象的常用属性:

属性描述
textHTTP响应内容的字符串形式,即URL对应的页面内容
contentHTTP响应内容的二进制形式
encodingHTTP响应内容的编码方式
status codeHTTP请求的返回状态,为整数,如200表示连接成功、404表示连接失败

除了属性,Response对象还提供了两个常用的方法:

  • json()方法:如果HTTP响应内容包含JSON格式数据,则该方法解析JSON数据。

提示:
JSON的全称是“JavaScript Object Notation”,即JavaScript对象表示法,是一种基于文本又独立于语言的轻量级数据交换格式,易于阅读和理解。

>>>import requests			#导入requests库
>>>r = requests.get('http://ip.taobao.com/service/getIpInfo.php?ip=122.88.60.28')
>>>r.json()				#调用json()方法
{'code': 0, 'data': {'ip': '122.88.60.28', 'country': '中国', 'area': '', 'region': '江苏', 'city': '南京', 'county': 'XX', 'isp': '铁通', 'country_id': 'CN', 'area_id': '', 'region_id': '320000', 'city_id': '320100', 'county_id': 'xx', 'isp_id': '100020'}}
  • raise_for_status()方法:该方法能在非成功响应后产生异常,即只要返回的请求状态status_code不是200,该方法就会产生一个异常,可用try-except异常处理结果进行处理。

提示:
一般情况下,需要在发送HTTP请求之后,调用raise_for_status()方法判断有无发生异常,如果没有发生异常,则进行数据的处理,否则不进行数据处理。

简单应用
# 例:爬取“http://www.bjjqe.com”网站的内容,并将爬取到的内容输出。
import requests				#导入requests库
#异常处理
try:
    r = requests.get('http://www.bjjqe.com')#使用get函数打开指定的url
    r.raise_for_status()			#如果状态不是200,则引发异常
    r.encoding = 'utf-8'			#更改编码方式
    print(r.text)				#用字符串的形式显示页面内容
except:
    print("网站连接失败!")		#发生异常则输出“网站连接失败!”

数据解析

正则表达式
  1. 正则表达式基础
    正则表达式是用于处理字符串的强大工具,它使用预定义的特定模式去匹配一类具有共同特征的字符串,主要用于快速、准确地完成复杂字符串的查找、替换等。
元字符和语法说 明表达式实例
字 符
一般字符匹配自身python匹配python
.匹配除换行符外的任意单个字符a.c匹配abc,acc等
|转义字符a.c匹配a.c;a\c匹配a\c
[ ]用来表示一组字符a[bcd]e(同a[b-d]e)匹配abe,ace和ade
[^ ]不在[ ]中的字符[^abc]匹配除a,b,c之外的字符
预定义字符集(可用在字符集[ ]中)
\d匹配任意数字,等价于[0-9]a\dc匹配a1c,a2c等
\D匹配任意非数字a\Dc匹配abc,asc等
\s匹配任意空白字符,等价于[\t\n\r\f]a\sc匹配a c
\S匹配任意非空字符a\Sc匹配abc等
\w匹配数字、字母、下划线a\wc匹配a1c,abc等
\W匹配非数字、字母、下划线a\Wc匹配a c
数量词(可用在字符或( )之后)
*匹配位于* 之前的字符0次或多次abc*匹配ab,abccc等
+匹配位于+之前的字符1次或多次abc+匹配abc,abccc等
?匹配位于?之前的字符0次或1次,当此字符紧随任何其他限定符(*、+、?、{m}、{m,n})之后时,匹配模式为“非贪婪”abc?匹配ab和abc
{m}匹配前一个字符m次ab{2}c匹配abbc
{m,n}匹配前一个字符m至n次,省略m则匹配0至n次;省略n则匹配m至无限次ab{1,2}c匹配abc和abbc
边界匹配
^匹配行首^abc匹配以abc开始的行
$匹配行尾abc$匹配以abc结尾的行
逻辑、分组
|匹配位于|之前或之后的字符a|b匹配a或b
( )将位于( )内的内容作为一个整体(abc){2}匹配abcabc

具体应用时,可以单独使用某种类型的元字符,但处理复杂字符串时,经常需要将多个正则表达式元字符进行组合。下面给出了几个示例。

  • (1)'[a-zA-Z0-9]'可以匹配一个任意大小写字母或数字。
  • (2)'^(\w){6,15}$'匹配长度为6~15的字符串,可以包含数字、字母和下划线。
  • (3)'^\w+@(\w+.)+\w+$'检查给定字符串是否为合法电子邮件地址。
  • (4)'\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}$'检查给定字符串是否为合法IP地址。
  1. re模块
    在Python中,主要使用re模块来实现正则表达式的操作,该模块的常用方法下表所示。
    | 方 法 | 描 述 |
    | ---------------------------------------- | ---------------------------------------- |
    | re.compile(pattern[, flags]) | 用于编译正则表达式,生成一个正则表达式(Pattern)对象 |
    | re.search(pattern, string[, flags])或search(string[, pos[, endpos]]) | 扫描整个字符串并返回第一个成功的匹配 |
    | re.match(pattern, string[, flags])或match(string[, pos[, endpos]]) | 尝试从字符串的起始位置匹配一个模式,返回match()对象或none |
    | re.findall(pattern, string[, flags])或findall(string[, pos[, endpos]]) | 在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表 |
    | re.sub(pattern, repl, string[, count=0])或sub(repl, string[, count]) | 用于替换字符串中的匹配项 |
    | re.split(pattern, string[, maxsplit=0])或split(string[, maxsplit]) | 按照能够匹配的子串将字符串分割后返回列表 |
    1. 直接使用re模块方法
>>>import re			#导入re模块
>>>text = 'Python.C.Java...PHP'	#定义text字符串
>>>re.split('[\.]+',text)		#调用split()函数对text进行分割
['Python', 'C', 'Java', 'PHP']
>>>re.findall('[a-zA-Z]+',text)	#调用findall()函数查找由大小写字母组成的字符串
['Python', 'C', 'Java', 'PHP']
    1. 使用正则表达式对象
      编译后的正则表达式对象不仅可以提高字符串的处理速度,还提供了更加强大的字符串处理功能。此处,我们首先使用re模块的compile()方法将正则表达式编译成正则表达式对象,然后使用正则表达式对象提供的方法进行字符串处理。
>>>import re				#导入re模块
>>>p = re.compile(r'\d+')		#将正则表达式编译成正则表达式对象
>>>print(p.findall('one1two2three3four4'))#调用findall()方法查找数字
['1','2','3','4']
# 例:爬取“http://www.bjjqe.com”网站的内容,解析数据,将该网站上的“.jpg“图片下载到本地。

1. 爬取网站内容:
可用正则表达式r'src=".+?\.jpg"'来匹配字符串

2. 在正则表达式中包含子组:
r'src="(.+?\.jpg)"'

3. 下载图片:
1)将获取到的每条路径加到“http://www.bjjqe.com”后面构成完整的链接地址
2)使用requests.get()函数获取内容,并将获取到的内容以二进制形式写入到文件中进行保存。
import requests			#导入requests库
import re			#导入re模块
#定义一个getHtml()函数,根据填写的url参数获取数据
def getHtml(url):
    #异常处理
    try:
        r = requests.get(url)		#使用get函数打开指定的url
        r.raise_for_status()		#如果状态不是200,则引发异常
        r.encoding = 'utf-8'		#更改编码方式
        return r.text			#返回页面内容
    except:
        return ""			#发生异常返回空字符
#定义一个getImg()函数,根据填写的html参数获取图片并存储
def getImg(html):
    reg=r'src="(.+?\.jpg)"'			#定义正则表达式
    imglist=re.findall(reg,html)		#查找页面中所有符合条件的字符串
    print(imglist)				#输出列表结果
    i = 0					#定义i用于给下载的图片命名
    for url in imglist:			#遍历
        with open(str(i)+".jpg","wb") as fd:	#以写入方式打开二进制文件
         #路径前加上“http://www.bjjqe.com”
            response=requests.get("http://www.bjjqe.com/"+url)#获取内容
            fd.write(response.content)	#写入文件
            print('图片',i,"保存成功\n")		#输出提示信息
            i+=1				#i加1
html = getHtml("http://www.bjjqe.com/")	#调用获取页面内容函数
getImg(html)				#调用获取图片并存储函数
beautifulsoup4库

beautifulsoup4库也称为Beautiful Soup库bs4库,用于解析和处理HTML和XML文件,其最大优点是能够根据HTML和XML语法建立解析树,进而提高解析效率。

有以下HTML文件:

<html>
	<head></head>
	<body>
		<a>first</a>
		<a>second</a>
	</body>
</html>
      |
      v
    |html|
      |
   ————————
  |        |
|head|   |body|
            |
         |a   |a

由于beautifulsoup4库是第三方库,因此,需要通过pip3指令进行安装,pip3安装命令如下:

>>>C:\>pip3 install beautifulsoup4

beautifulsoup4库中最重要的类是BeautifulSoup,它的实例化对象相当于一个页面。
可采用from-import语句导入库中的BeautifulSoup类,然后使用**BeautifulSoup()**创建一个BeautifulSoup对象。

# 例子:
>>>import requests			#导入requests库
>>>from bs4 import BeautifulSoup		#从bs4库中导入BeautifulSoup类
>>>r = requests.get('http://www.baidu.com')	#使用get函数打开百度链接
>>>r.encoding = 'utf-8'			#更改编码方式
>>>soup = BeautifulSoup(r.text)		#创建BeautifulSoup对象
>>>type(soup)				#查看soup类型
<class 'bs4.BeautifulSoup'>

创建的BeautifulSoup对象是一个树形结构,它包含HTML页面中的标签元素,如、等。也就是说,HTML中的主要结构都变成了BeautifulSoup对象的一个属性,可通过“对象名.属性名”形式获取属性值。

属 性描 述
headHTML页面的内容
titleHTML页面标题,在中,由标记
bodyHTML页面的内容
pHTML页面中第一个

内容

aHTML页面中第一个内容
stringsHTML页面所有呈现在Web上的字符串,即标签的内容
stripped_stringsHTML页面所有呈现在Web上的非空格字符串

每一个标签在beautifulsoup4库中又是一个对象,称为Tag对象。

# 例子:查看“soup.p”的类型可以看出“soup.p”是一个Tag对象:
>>>type(soup.p)			#查看“soup.p”类型
<class 'bs4.element.Tag'>

Tag对象有4个常用属性

属 性描 述
name字符串,标签的名字,如head,title等
attrs字典,包含了页面标签的所有属性(尖括号内的其他项),如href
contents列表,这个标签下所有子标签的内容
string字符串,标签所包围的文字,网页中真实的文字(尖括号之间的内容)

当需要列出对应标签的所有内容或找到非第一个标签时,可以使用BeautifulSoup对象的find_all()方法。该方法会遍历整个HTML文件,按照条件返回标签内容(列表类型)。
其语法格式如下:

对象名.find_all(name, attrs,recursive, string, limit)

'''
name 表示标签名;
attrs 表示按照标签属性值检索(需列出属性名和值);
recursive 表示查找层次(Beautiful Soup默认检索当前标签的所有子孙节点,如果只搜索标签的直接子节点,可以使用参数recursive = False);
string 表示按照关键字检索string属性内容(采用string = 开始);
limit 表示返回结果的个数,默认返回全部结果。
'''
# 例:爬取“http://www.bjjqe.com”网站的内容,解析数据,输出该网站中的图书信息。
import requests				#导入requests库
import re				#导入re模块
from bs4 import BeautifulSoup		#导入BeautifulSoup
#定义一个getHtml()函数,根据填写的url参数获取数据
def getHtml(url):
    #异常处理
    try:
        r = requests.get(url)			#使用get函数打开指定的url
        r.raise_for_status()			#如果状态不是200,则引发异常
        r.encoding = 'utf-8'			#更改编码方式
        return r.text				#返回页面内容
    except:
        return ""				#发生异常返回空字符

#定义数据解析函数,用于找到符合条件的数据并输出
def getcon(html):
    bsObj = BeautifulSoup(html)		#将html对象转化为BeautifulSoup对象
    #找到所有class为bk_show_info的div,只获取图书信息
    divList = bsObj.find_all('div',{'class':'bk_show_info'}) 
    allbook = []				#存储全部数据,二维列表
    for divs in divList:
        book_info = []			#存储单本图书信息,一维列表
        book_name = divs.h4['data-name']	#获取图书名称
        book_info.append(book_name)	#将图书名称存储到book_info
        p_list = divs.find_all('p')		#查找单本图书的其他信息(在标签p中)
        for p_content in p_list:
    	    book_info.append(p_content.string)#将p标签中的信息存入book_info
        allbook.append(book_info)		#将单本图书的信息存入allbook
    #输出获取到的图书信息
    for book in allbook:
        print(book)
html = getHtml("http://www.bjjqe.com/")	#调用获取页面内容函数
getcon(html)				#调用解析数据函数

pygame简介

  • pygame是一组用来开发游戏的Python程序模块,它是在SDL库的基础上开发的。
  • 用户可以利用它,在Python程序中创建功能丰富的游戏和多媒体程序。
  • pygame是一组高可移植性的模块,可以支持多个操作系统,非常适合小游戏的开发。

提示:
SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用C语言编写而成。SDL提供了数种控制图形、图像、声音、输入和输出的函数,使用户只要用相同或相似的代码就可以开发出跨多个平台(Linux,Windows,Mac OS X等)的应用软件。目前SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。

  1. 由于pygame不是Python默认集成的模块,因此,需要通过pip3指令进行安装,pip3安装命令如下:
C:\>pip3 install pygame
  1. 安装完成后,输入以下命令,如果出现如下图所示示例图,则说明安装成功。
C:\>python -m pygame.examples.aliens

提示:
如果pip3指令安装不成功,可登录http://www.pygame.org/download.shtml网站,找到对应Python版本的pygame模块,下载之后直接默认安装即可。

pygame常用功能

创建窗口并显示图片

pygame中最重要的就是surface对象,它是pygame用来表示图像的对象。

  1. pygame.display.set_mode()方法
    pygame.display.set_mode()方法用于初始化一个窗口或屏幕。
    其方法原型如下:
set_mode(resolution=(0,0), flags=0, depth=0)

'''
resolution=(0,0) 是一个二元组,表示宽和高
flags=0  指定扩展选项
depth=0  表示使用的颜色深度
'''
选 项含 义
FULLSCREEN创建一个全屏显示
DOUBLEBUF双缓冲模式(推荐与HWSURFACE或OPENGL一起使用)
HWSURFACE硬件加速,只有在FULLSCREEN下可以使用
OPENGL创建一个OPENGL渲染的显示
RESIZABLE创建一个可调整尺寸的窗口
NOFRAME创建一个没有边框和控制按钮的窗口
  1. pygame.image.load()方法
    pygame.image.load()方法用于加载一张新的图片。
    其方法原型如下:
load(filename)
# filename  为要加载的图片的名称(可包含路径)

使用pygame.image.load()可创建一个包含图像的surface对象。创建完surface对象后,要想显示图像,还需要调用blit()方法,该方法用于将一个图像(surface对象)绘制到另一个图像上方。
其方法原型如下:

blit(source, dest[, area=None, special_flags = 0])

# source  为要加载的图片的名称(可包含路径)
# dest  为坐标值,一般为source的左上角坐标
# 例:创建一个窗口,并加载一张图片作为窗口的背景。
#导入所需模块
import pygame, sys
#导入所有pygame.locals里的变量(比如下面大写的QUIT变量) 
from pygame.locals import *
#初始化pygame 
pygame.init()
#设置窗口大小,单位为像素
screen = pygame.display.set_mode((500, 400))
#创建一个背景图片
background = pygame.image.load("./pic/back.png")
#设置窗口标题
pygame.display.set_caption('Hello World')


#程序主循环 
while True:
    #把背景复制到窗口的(0,0)处贴进去
    screen.blit(background, (0,0))	
    #获取事件
    for event in pygame.event.get():
    #判断事件是否为退出事件 
        if event.type == QUIT: 
            pygame.quit()	       #退出pygame 
            sys.exit()		       #退出系统
    pygame.display.update()    #绘制屏幕内容

提示:
如果想要全屏显示游戏界面,可在调用pygame.display.set_mode()方法时设置第二个参数为FULLSCREEN,同时加上硬件加速HWSURFACE,即:
screen = pygame.display.set_mode((500, 400),FULLSCREEN | HWSURFACE)

绘制图形

pygame中绘制图形的模块是pygame.draw,该模块中常用的方法如下表所示。

方 法作 用
pygame.draw.line(surface, color, start_pos, end_pos, width)绘制一条线段
pygame.draw.aaline(surface, color, start_pos, end_pos, blend)绘制一条抗锯齿的线
pygame.draw.lines(surface, color, closed, pointlist, width)绘制一条折线
pygame.draw.rect(surface, color, Rect)绘制一个矩形
pygame.draw.ellipse(surface, color, Rect)绘制一个椭圆
pygame.draw.ellipse(surface, color, Rect, width)绘制一个椭圆框
pygame.draw.polygon(surface, color, pointlist, width)绘制一个多边形
pygame.draw.arc(surface, color, Rect, start_angle, stop_angle, width)绘制一条弧线
pygame.draw.circle(surface, color, Rect, radius)绘制一个圆
  • pygame.draw方法的第一个参数总是surface(即surface对象名);
  • 接下来是参数color,表示颜色;
  • 再后就是一系列坐标等。
# 例:绘制图形实例。
#导入需要的模块
import pygame, sys
from pygame.locals import *
from math import pi
#初始化pygame
pygame.init()
#设置窗口大小,单位为像素 
screen = pygame.display.set_mode((400,300))
#设置窗口标题 
pygame.display.set_caption('Drawing')
#定义颜色 
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)

#设置背景颜色
screen.fill(WHITE)
#绘制一条线
pygame.draw.line(screen, RED, [0, 10], [50,10], 2)
#绘制一条抗锯齿的线
pygame.draw.aaline(screen, GREEN, [0, 50],[50, 50],True)
#绘制一条折线
pygame.draw.lines(screen, BLACK, False, [[0, 80], [50, 80], [50, 120]], 5)
#绘制一个空心矩形
pygame.draw.rect(screen, BLACK, [75, 10, 50, 20], 2)
#绘制一个矩形
pygame.draw.rect(screen, BLACK, [150, 10, 50, 20])
#绘制一个空心椭圆
pygame.draw.ellipse(screen, RED, [225, 10, 50, 20], 2)
#绘制一个椭圆
pygame.draw.ellipse(screen, RED, [300, 10, 50, 20])

提示:
fill()方法的作用是使用纯色填充surface对象。

#绘制多边形(三角形)
pygame.draw.polygon(screen, BLACK, [[120, 150], [0, 200], [200, 200]], 5)
#绘制多条弧线
pygame.draw.arc(screen, BLACK,[210, 75, 150, 125], 0, pi/2, 2)
pygame.draw.arc(screen, GREEN,[210, 75, 150, 125], pi/2, pi, 2)
pygame.draw.arc(screen, BLUE, [210, 75, 150, 125], pi,3*pi/2, 2)
pygame.draw.arc(screen, RED, [210, 75, 150, 125], 3*pi/2, 2*pi, 2)
#绘制一个圆
pygame.draw.circle(screen, BLUE, [200, 250], 40)


#程序主循环
while True:
#获取事件
    for event in pygame.event.get():
    #判断事件是否为退出事件
        if event.type == QUIT:
            pygame.quit()			#退出pygame 
            sys.exit()   				#退出系统
    pygame.display.update()			#绘制屏幕内容
动画效果
  • 物体移动的原理很简单,即在原有坐标的基础上增加偏移量,再重新绘制图片,依次一张一张地循环绘制下去,就可以得到物体移动的效果。
  • 还有一个问题就是两个画面之间的时间间隔,即经过多长时间绘制下一张图片。
  • pygame.time模块提供了一个Clock对象,调用其tick()方法即可解决上述问题:
    • (1)pygame.time.Clock()用于实例化对象以获得pygame的时钟。
    • (2)调用pygame.time.Clock.tick(FPS)方法设置pygame时钟的间隔时间,其中参数FPS即为帧率(帧率即为每秒钟显示的帧数)。
# 例:动画效果实例。
#导入需要的模块
import pygame, sys
from pygame.locals import *
#初始化pygame
pygame.init()
# 设置帧率(屏幕每秒刷新的次数)
FPS = 30
#获得pygame的时钟
fpsClock = pygame.time.Clock()
#设置窗口大小
screen = pygame.display.set_mode((500, 400), 0, 32)
#设置标题
pygame.display.set_caption('Animation')
#定义颜色
WHITE = (255, 255, 255)


#加载一张图片
img = pygame.image.load('./pic/yundong.png')
#初始化图片的位置
imgx = 10
imgy = 10
#初始化图片的移动方向
direction = 'right'
#程序主循环
while True:
    #每次都要重新绘制背景白色
    screen.fill(WHITE)
    #判断移动的方向,并对相应的坐标作加减
    if direction == 'right':
        imgx += 5
        if imgx == 380:
            direction = 'down'
    elif direction == 'down':
        imgy += 5
        if imgy == 300:
            direction = 'left'
    elif direction == 'left':
        imgx -= 5
        if imgx == 10:
            direction = 'up'
    elif direction == 'up':
        imgy -= 5
        if imgy == 10:
            direction = 'right'     


#该方法用于将图片绘制到相应的坐标中
    screen.blit(img, (imgx, imgy))
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
    #刷新屏幕
    pygame.display.update()
    #设置pygame时钟的间隔时间
    fpsClock.tick(FPS)  
播放声音

对于一般游戏来说,声音分为音效和背景音乐两种。

  • 音效是在某种条件下被触发播放的,音效可采用无压缩的wav格式。
  • 而背景音乐则是时刻伴随着游戏存在的,背景音乐可采用ogg格式或者mp3格式。
  1. 播放音效
    播放音效使用mixer模块,需要首先生成一个Sound对象,其具体语法格式如下:
pygame.mixer.Sound(filename)

# filename  filename为音频文件名(可包含路径)
方 法含 义方 法含 义
play()播放音效get_volume()获取音量
stop()停止播放get_num_channels()计算该音效播放的次数
fadeout()淡出get_length()获取音效的长度
set_volume()设置音量get_raw()将音效以二进制格式返回
  1. 播放背景音乐
    播放背景音乐使用music模块,music模块是mixer模块中的一个特殊实现,可使用pygame.mixer.music来调用该模块下的方法。
    music模块支持的常用方法如下表所示:
方 法含 义方 法含 义
load()载入音乐get_volume()获取音量
play()播放音乐get_busy()检查是否正在播放音乐
rewind()重新播放音乐set_pos()设置播放的位置
stop()结束音乐播放get_pos()获取播放的位置
pause()暂停音乐播放queue()将一个音乐文件放入待播放队列中
unpause()恢复音乐播放set_endevent()当播放结束时发出一个事件
fadeout()淡出get_endevent()获取播放结束时发送的事件
set_volume()设置音量
#导入需要的模块
import pygame, sys
from pygame.locals import *
#初始化pygame
pygame.init()
#设置窗口大小,单位为像素
screen = pygame.display.set_mode((200,150))
#设置窗口的标题
pygame.display.set_caption('Audio')
#定义颜色 
WHITE = (255, 255, 255)
#设置背景颜色
screen.fill(WHITE)
#加载并播放一个特效音频文件
sound = pygame.mixer.Sound('sound/bird.wav')


sound.play()
#加载背景音乐文件
pygame.mixer.music.load('sound/Remember.mp3')
#播放背景音乐,第一个参数为播放的次数(-1表示无限循环),第二个参数是设置播放的起点(单位为秒)
pygame.mixer.music.play(-1, 0.0)
#程序主循环


while True:
    #获取事件
    for event in pygame.event.get():
        #判断事件是否为退出事件 
        if event.type == QUIT:
            #停止播放背景音乐
            pygame.mixer.music.stop()
            #退出pygame
            pygame.quit()
            #退出系统
            sys.exit()
    #绘制屏幕内容
    pygame.display.update()
显示文字

如果想要将文字显示到屏幕上,可首先使用pygame.font.Font()创建一个Font对象,其语法格式如下:

pygame.font.Font(filename, size)

# filename  字体文件的文件名(一般为“.ttf”格式的文件)
# size  字体的大小,单位为像素

创建Font对象后,就可以使用render()方法绘制文本了,其语法格式如下:

pygame.font.Font.render(text, antialias, color, background=None)

# text  要显示的文字
# antialias  是个布尔值,决定是否开启抗锯齿,当为True时字体比较平滑
# color  字体颜色
# background=None  背景颜色

最后需要调用blit()方法显示文字

# 例:显示文字实例。
#导入需要的模块
import pygame, sys
from pygame.locals import *
#初始化pygame
pygame.init()
#设置窗口大小,单位为像素
screen = pygame.display.set_mode((300,200))
#设置窗口标题
pygame.display.set_caption('Font')
#定义颜色
WHITE = (255, 255, 255)
RED = ( 255, 0, 0)
GREEN = ( 0, 255, 0)
#通过字体文件获得字体对象
fontObj = pygame.font.Font('ziti/FZQTFW.TTF', 50)


#配置要显示的文字
textSurfaceObj = fontObj.render('Pygame', True, GREEN, RED)
#获得要显示的对象的rect
textRectObj = textSurfaceObj.get_rect()
#设置显示对象的坐标 
textRectObj.center = (150, 100)
#设置背景
screen.fill(WHITE)
#绘制字体
screen.blit(textSurfaceObj, textRectObj)


#程序主循环
while True:
    #获取事件
    for event in pygame.event.get():
        #判断事件是否为退出事件
        if event.type == QUIT:
            #退出pygame
            pygame.quit()
            #退出系统
            sys.exit()
    #绘制屏幕内容
    pygame.display.update()

提示:
可通过get_rect()方法获得一个对象的结构,以便于设置其坐标位置。

事件
  • 事件是pygame提供的干预机制。
  • pygame会接收用户的各种操作(如敲击键盘、移动鼠标、单击鼠标等)产生事件。
  • 一般可使用pygame.event.get()方法来处理所有事件,pygame中常用的事件及含义如下表所示:

|事 件|含 义|属 性|
|QUIT|用户按下关闭按钮|none|
|ACTIVEEVENT|Pygame被激活或者隐藏|gain,state|
|KEYDOWN|键盘被按下|unicode,key,mod|
|KEYUP|键盘被放开|key,mod|
|MOUSEMOTION|鼠标移动|pos,rel,buttons|
|MOUSEBUTTONDOWN|鼠标按下|pos,button|
|MOUSEBUTTONUP|鼠标放开|pos,button|
|VIDEORESIZE|pygame窗口缩放|size,w,h|

# 例:事件实例。

#导入需要的模块
import pygame, sys
from pygame.locals import *
#定义颜色
WHITE = (255, 255, 255)
#初始化pygame
pygame.init()
#设置窗口大小,单位为像素
screen = pygame.display.set_mode((300,200), 0, 32)
#设置窗口标题
pygame.display.set_caption('Event')
#设置背景
screen.fill(WHITE)


#程序主循环
while True:
    #获取事件
    for event in pygame.event.get():
        #判断事件是否为退出事件
        if event.type == QUIT:
            #退出pygame
            pygame.quit()
            #退出系统
            sys.exit()
        #获得鼠标当前位置
        if event.type == MOUSEMOTION:
            print(event.pos)
        #获得鼠标按下的位置
        if event.type == MOUSEBUTTONDOWN:
            print("鼠标按下:",event.pos)


#获得鼠标抬起的位置
        if event.type == MOUSEBUTTONUP:
            print("鼠标抬起:",event.pos)
        #获得键盘按下的事件
        if event.type == KEYDOWN:
            if(event.key==K_UP): 
                print("上")
            if(event.key==K_DOWN):
                print("下")
            if(event.key==K_LEFT):
                print("左")
            if(event.key==K_RIGHT):
                print("右")
            #按下键盘的Esc键退出
            if(event.key==K_ESCAPE):
                #退出pygame
                pygame.quit()
                #退出系统
                sys.exit()
    #绘制屏幕内容
    pygame.display.update()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值