其他复习资料
Python期末复习-系列数据类型-CSDN博客
期末python复习-异常和函数-CSDN博客
期末Python复习-输入输出-CSDN博客
目录
一、面向对象程序设计
1.思维导图
2.基本概念
3.类对象和实例对象
3.1创建对象
3.2定义类中的成员变量
3.3类中属性的公有和私有
3.4特殊属性
4.方法
4.1声明类中的方法
编辑
4.2静态方法
4.3类方法
4.4私有方法和公有方法
4.5方法重载
5.继承
5.1 类成员对父类方法的继承和重写
6.对象的特殊方法
7.对象的引用、浅拷贝和深拷贝
7.1浅拷贝
7.2深拷贝
二、数据结构
1.思维导图
2.集合
3.字典
三、网络编程和通信
1.思维导图
2.基本概念
3.基于socket的网络编程
3.1TCP
3.2UDP
4.基于http的网路编程
5.基于 poplib 和 smtplib 的网络编程
四、并行计算:进程、线程和协程
1.思维导图
2.并发处理概述
3.基于线程的并发处理(使用Threading库)
3.1使用Thread对象创建线程
4.基于进程的并行计算(使用multiprocessing标准库)
5.基于asyncio的异步IO编程(asyncio标准库)
一、面向对象程序设计
1.思维导图
2.基本概念
面向对象的三大特性:封装、继承。多态
对象的定义 某种事物的抽象(功能)
抽象原则包括数据抽象和过程抽象两个方面 数据抽象-定义对象属性;过程抽象-定义对象操作(其实就是属性和方法)
封装 把客观事物抽象并封装成对象
继承 允许使用现有类的功能,并在无需重新改写原来的类的情况下,对这些功能进行扩展
多态性:对象可以表示多个类型的能力
3.类对象和实例对象
3.1创建对象
创建一个类和对象的示例代码如下:
class Person1: #定义类Person1
pass #类体为空语句
#测试代码
p1 = Person1() #创建和使用类对象
print(Person1, type(Person1), id(Person1))
print(p1, type(p1), id(p1))
3.2定义类中的成员变量
定义类中成员变量的代码如下:(通过self.变量名定义的属性)
【例9.3】定义类Person2。定义成员变量(域)
class Person2: #定义类Person2
def __init__(self, name,age): #__init__方法
self.name = name #初始化self.name,即成员变量name(域)
self.age = age #初始化self.age,即成员变量age(域)
def say_hi(self): #定义类Person2的函数say_hi()
print('您好, 我叫', self.name) #在实例方法中通过self.name读取成员变量name(域)
#测试代码
p1 = Person2('张三',25) #创建对象
p1. say_hi () #调用对象的方法
print(p1.age) #通过p1.age(obj1.变量名)读取成员变量age(域)
3.3类中属性的公有和私有
属性分有私有属性和公有属性
两个下划线开头,但是不以两个下划线结束的属性是私有的(private),其他为公共的(public)
【例9.5】私有属性示例(private.py)
class A:
__name = 'class A' #私有类属性
def get_name():
print(A.__name) #在类方法中访问私有类属性
#测试代码
A.get_name()
A.__name #导致错误,不能直接访问私有类属性
3.4特殊属性
其实就类似java中的构造方法、equals方法、tostring方法等
【例9.9】自定义属性示例
class CustomAttribute(object):
def __init__(self):
pass
def __getattribute__(self, name):
return str.upper(object.__getattribute__(self, name))
def __setattr__(self, name, value):
object.__setattr__(self, name, str.strip(value))
#测试代码
o = CustomAttribute()
o.firstname=' mary '
print(o.firstname)
4.方法
4.1声明类中的方法
实例方法示例。定义类Person4,创建其对象,并调用对象函数
class Person4: #定义类Person4
def say_hi(self, name): #定义方法say_hi
self.name = name #把参数name赋值给self.name,即成员变量name(域)
print('您好, 我叫', self.name)
p4 = Person4() #创建对象实例
p4.say_hi('Alice') #调用对象实例的方法
4.2静态方法
静态方法与类的实例无关,与类有关,可以通过类名.方法名直接调用
静态方法的定义如下:
访问静态方法的语法如下:
代码示例如下:
class MathTools:
@staticmethod
def add(x, y):
"""静态方法,用于计算两个数的和"""
return x + y
@staticmethod
def multiply(x, y):
"""静态方法,用于计算两个数的乘积"""
return x * y
# 调用静态方法,不需要创建类的实例
result_add = MathTools.add(5, 3)
result_multiply = MathTools.multiply(4, 2)
print(f"5 + 3 = {result_add}")
print(f"4 * 2 = {result_multiply}")
输出结果如下:
5 + 3 = 8
4 * 2 = 8
4.3类方法
类方法:属于类本身的方法
类方法和静态方法最大的区别就是:类方法需要被实例化才能够使用,静态方法不需要被实例化就能使用
类方法的定义语法
访问类方法的语法
类方法代码示例:
class Person:
# 类变量,存储所有实例的姓名
people_names = []
def __init__(self, name):
# 实例变量,存储个人的姓名
self.name = name
@classmethod
def add_name(cls, name):
"""类方法,用于添加姓名到类变量people_names中"""
cls.people_names.append(name)
@classmethod
def get_names(cls):
"""类方法,用于获取类变量people_names中的所有姓名"""
return cls.people_names
# 使用类方法添加姓名
Person.add_name("Alice")
Person.add_name("Bob")
# 使用类方法获取所有姓名
all_names = Person.get_names()
print("所有人员姓名:", all_names)
4.4私有方法和公有方法
两个下划线开头,但不以两个下划线结束的方法是私有的(private),其他为公共的(public)
以双下划线开始和结束的方法是Python的专有特殊方法。不能直接访问私有方法,但可以在其他方法中访问,例如构造函数和new方法、del方法等
私有方法代码示例:
class Account:
def __init__(self, balance=0):
self.__balance = balance # 私有属性
def deposit(self, amount):
"""存款方法,向账户中增加金额"""
if amount > 0:
self.__balance += amount
print(f"存入{amount}元,当前余额为{self.__balance}元")
else:
print("存款金额必须大于0")
def withdraw(self, amount):
"""取款方法,从账户中取出金额"""
if amount > 0 and amount <= self.__balance:
self.__balance -= amount
print(f"取出{amount}元,当前余额为{self.__balance}元")
else:
print("取款金额无效或余额不足")
def __check_balance(self, amount):
"""私有方法,检查余额是否充足"""
if self.__balance >= amount:
print("余额充足")
return True
else:
print("余额不足")
return False
# 创建账户实例
account = Account(100)
# 存款
account.deposit(50)
# 取款
account.withdraw(30)
# 尝试调用私有方法(这将导致错误)
# account.__check_balance(20) # 这行代码将无法正常运行,因为__check_balance是私有方法
在这个例子中,Account
类有一个私有属性__balance
,用来存储账户的余额。deposit
和withdraw
是两个公共方法,分别用于存款和取款。__check_balance
是一个私有方法,用于检查账户余额是否充足。
私有方法__check_balance
只能在类内部被调用,例如在withdraw
方法中,我们可以通过self.__check_balance(amount)
来调用它。如果你尝试在类的外部直接调用私有方法,Python将会抛出一个AttributeError
。
请注意,Python中的私有化只是一种约定,并不是强制的。即使方法或属性以两个下划线开头,外部代码仍然可以通过_ClassName__MethodName
的方式访问到它们,但这是一种不推荐的做法,因为它违反了封装的原则。
4.5方法重载
可以定义多个重名的方法,只要保证方法签名是唯一的
方法签名包括三个部分:方法名、参数数量和参数类型
方法重载代码示例:
class Person22: #定义类Person22
def say_hi(self, name): #定义类方法say_hi,带两个参数
print('您好, 我叫', self.name)
def say_hi(self, name, age): #定义类方法say_hi,带三个参数
print('hi, {0}, 年龄:{1}'.format(name,age))
p22 = Person22() #创建对象
p22.say_hi('Lisa', 22) #调用对象的方法
#p22.say_hi('Bob') #TypeError: say_hi() missing 1 required positional argument: 'age'
5.继承
派生类:Python支持多重继承,即一个派生类可以继承多个基类
基本语法如下:
声明派生类时,必须在其构造函数中调用基类的构造函数
代码示例如下:
创建基类Person,包含两个数据成员name和age;创建派生类Student,包含一个数据成员stu_id
class Person: #基类
def __init__(self, name, age): #构造函数
self.name = name #姓名
self.age = age #年龄
def say_hi(self): #定义基类方法say_hi
print('您好, 我叫{0}, {1}岁'.format(self.name,self.age))
class Student(Person): #派生类
def __init__(self, name, age, stu_id): #构造函数
Person.__init__(self, name, age) #调用基类构造函数
self.stu_id = stu_id #学号
def say_hi(self): #定义派生类方法say_hi
Person.say_hi(self) #调用基类方法say_hi
print('我是学生, 我的学号为:', self.stu_id)
p1 = Person('张王一', 33) #创建对象
p1.say_hi()
s1 = Student('李姚二', 20, '2018101001') #创建对象
s1.say_hi()
5.1 类成员对父类方法的继承和重写
代码示例如下:
class Dimension: #定义类Dimensions
def __init__(self, x, y): #构造函数
self.x = x #x坐标
self.y = y #y坐标
def area(self): #基类的方法area()
pass
class Circle(Dimension): #定义类Circle(圆)
def __init__(self, r): #构造函数
Dimension.__init__(self, r, 0)
def area(self): #覆盖基类的方法area()
return 3.14 * self.x * self.x #计算圆面积
class Rectangle(Dimension): #定义类Rectangle(矩形)
def __init__(self, w, h): #构造函数
Dimension.__init__(self, w, h)
def area(self): #覆盖基类的方法area()
return self.x * self.y #计算矩形面积
d1 = Circle(2.0) #创建对象:圆
d2 = Rectangle(2.0, 4.0) #创建对象:矩形
print(d1.area(), d2.area()) #计算并打印圆和矩形面积
6.对象的特殊方法
包含许多以双下划线开始和结束的方法,称之为特殊方法
例如,创建对象实例时自动调用其__init__方法,a<b时,自动调用对象a的__lt__方法
特殊方法 | 含义 |
---|---|
__lt__ , __add__ 等 | 对应运算符 < 、+ 等。 |
__init__ , __del__ | 创建或销毁对象时调用。 |
__len__ | 对应于内置函数 len() 。 |
__setitem__ , __getitem__ | 按索引赋值、取值。 |
__repr__(self) | 对应于内置函数 repr() 。 |
__str__(self) | 对应于内置函数 str() 。 |
__bytes__(self) | 对应于内置函数 bytes() 。 |
__format__(self, format_spec) | 对应于内置函数 format() 。 |
__bool__(self) | 对应于内置函数 bool() 。 |
__hash__(self) | 对应于内置函数 hash() 。 |
__dir__(self) | 对应于内置函数 dir() 。 |
7.对象的引用、浅拷贝和深拷贝
7.1浅拷贝
浅拷贝是创建一个新对象,其内容是原对象中包含的对象的引用拷贝。这意味着,如果原对象中包含的是可变对象,那么在拷贝中对这些可变对象的修改将会影响到原对象。
优点:拷贝速度快,因为不需要复制对象中的每个元素。 缺点:如果原对象中的元素是可变的,那么拷贝和原对象将共享这些元素。
代码示例如下:
import copy
original_list = [1, 2, [3, 4], 5]
shallow_copied_list = copy.copy(original_list)
# 修改拷贝中的可变对象
shallow_copied_list[2].append(6)
print("原始列表:", original_list) # 输出: [1, 2, [3, 4, 6], 5]
print("浅拷贝列表:", shallow_copied_list) # 输出: [1, 2, [3, 4, 6], 5]
7.2深拷贝
深拷贝是创建一个新对象,并且递归地拷贝原对象中包含的所有对象。这意味着,深拷贝会创建一个完全独立的拷贝,其中包含的所有对象都是原对象中对象的副本。
优点:拷贝后的对象与原对象完全独立,修改拷贝不会影响原对象。 缺点:拷贝速度慢,因为需要递归复制对象中的每个元素。
代码示例如下:
import copy
original_list = [1, 2, [3, 4], 5]
deep_copied_list = copy.deepcopy(original_list)
# 修改拷贝中的可变对象
deep_copied_list[2].append(6)
print("原始列表:", original_list) # 输出: [1, 2, [3, 4], 5]
print("深拷贝列表:", deep_copied_list) # 输出: [1, 2, [3, 4, 6], 5]
二、数据结构
1.思维导图
2.集合
集合数据类型是没有顺序的简单对象的聚集,且集合中元素不重复
Python集合数据类型包括可变集合对象(set)和不可变集合对象(frozenset)
创建集合和常用集合方法的代码示例
# 创建一个空集合
empty_set = set()
# 创建一个包含一些元素的集合
my_set = {1, 2, 3, 4, 5}
# 打印集合
print("空集合:", empty_set) # 输出: set()
print("包含元素的集合:", my_set) # 输出: {1, 2, 3, 4, 5}
# 添加元素到集合
my_set.add(6)
print("添加元素6后的集合:", my_set) # 输出: {1, 2, 3, 4, 5, 6}
# 移除元素从集合
my_set.remove(4)
print("移除元素4后的集合:", my_set) # 输出: {1, 2, 3, 5, 6}
# 集合的并集
union_set = my_set.union({7, 8, 9})
print("集合的并集:", union_set) # 输出: {1, 2, 3, 5, 6, 7, 8, 9}
# 集合的交集
intersection_set = my_set.intersection({1, 2, 3, 4, 5, 10})
print("集合的交集:", intersection_set) # 输出: {1, 2, 3, 5}
# 集合的差集
difference_set = my_set.difference({1, 2, 3})
print("集合的差集:", difference_set) # 输出: {5, 6}
# 集合的对称差分
symmetric_difference_set = my_set.symmetric_difference({5, 6, 10})
print("集合的对称差分:", symmetric_difference_set) # 输出: {1, 2, 3, 10}
# 集合推导式
squares_set = {x**2 for x in range(10)}
print("集合推导式创建的平方数集合:", squares_set) # 输出: {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}
3.字典
python中的字典其实就跟java中的map集合是一样的概念,只是不同的叫法,一种存储键值对的数据结构
代码示例如下:
# 创建一个空字典
empty_dict = {}
# 创建一个包含一些键值对的字典
my_dict = {'name': 'Alice', 'age': 25, 'city': 'New York'}
# 打印字典
print("空字典:", empty_dict) # 输出: {}
print("包含键值对的字典:", my_dict) # 输出: {'name': 'Alice', 'age': 25, 'city': 'New York'}
# 访问字典中的值
print("名字:", my_dict['name']) # 输出: Alice
print("年龄:", my_dict.get('age')) # 输出: 25,使用get方法可以避免KeyError
# 添加新的键值对到字典
my_dict['email'] = 'alice@example.com'
print("添加邮箱后的字典:", my_dict) # 输出: {'name': 'Alice', 'age': 25, 'city': 'New York', 'email': 'alice@example.com'}
# 修改字典中的值
my_dict['age'] = 26
print("修改年龄后的字典:", my_dict) # 输出: {'name': 'Alice', 'age': 26, 'city': 'New York', 'email': 'alice@example.com'}
# 删除字典中的键值对
del my_dict['city']
print("删除城市后的字典:", my_dict) # 输出: {'name': 'Alice', 'age': 26, 'email': 'alice@example.com'}
# 检查键是否存在于字典中
if 'name' in my_dict:
print("字典中包含键 'name'") # 输出: 字典中包含键 'name'
# 获取字典的所有键
keys = my_dict.keys()
print("字典的所有键:", keys) # 输出: dict_keys(['name', 'age', 'email'])
# 获取字典的所有值
values = my_dict.values()
print("字典的所有值:", values) # 输出: dict_values(['Alice', 26, 'alice@example.com'])
# 获取字典的所有键值对
items = my_dict.items()
print("字典的所有键值对:", items) # 输出: dict_items([('name', 'Alice'), ('age', 26), ('email', 'alice@example.com')])
# 字典推导式
squares_dict = {x: x**2 for x in range(6)}
print("字典推导式创建的平方数字典:", squares_dict) # 输出: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
三、网络编程和通信
1.思维导图
2.基本概念
- 计算机网络是由传输介质连接在一起的一系列设备(网络节点)组成
- 在计算机网络中,用于规定信息的格式以及如何发送和接收信息的一套规则、标准或约定称为网络协议
- 网络编程就是通过网络协议与其他计算机进行通讯
- TCP/IP协议模型把TCP/IP协议族分成四个层次:图18-2
3.基于socket的网络编程
套接字:网络中两个应用程序之间通信的端点
3.1TCP
基于套接字的TCP Server的网络编程一般包括以下基本步骤
(1)创建socket对象。
(2)将socket绑定到指定地址上。
(3)准备好套接字,以便接收连接请求。
(4)通过socket对象方法accept,等待客户请求连接。
(5)服务器和客户机通过send和recv方法通信(传输数据)。
(6)传输结束,调用socket的close方法以关闭连接。
基于套接字的TCP Client的网络编程一般包括以下基本步骤
(1)创建socket对象。
(2)通过socket对象方法connect连接服务器。
(3)客户机和服务器通过send和recv方法通信(传输数据)。
(4)传输结束,调用socket的close方法以关闭连接。
3.2UDP
基于套接字的UDP Server的网络编程一般包括以下基本步骤
(1)创建socket对象。
(2)将socket绑定到指定地址上。
(3)服务器和客户机通过send和recv方法通信(传输数据)。
(4)传输结束,调用socket的close方法以关闭连接。
基于套接字的UDP Client的网络编程一般包括以下基本步骤
(1)创建socket对象。
(2)客户机和服务器通过send和recv方法通信(传输数据)。
(3)传输结束,调用socket的close方法以关闭连接。
4.基于http的网路编程
-
客户端-服务器模型:网络编程通常遵循客户端-服务器模型,其中服务器监听客户端的请求并提供响应。
-
URL和URI:统一资源定位器(URL)和统一资源标识符(URI)用于指定网络上的资源位置。
-
HTTP请求:客户端发送HTTP请求到服务器,请求包含方法(如GET、POST、PUT、DELETE等)、请求头和可能的请求体。
-
HTTP响应:服务器处理请求后,返回HTTP响应,响应包含状态码、响应头和响应体。
-
Python中的HTTP库:
http.client
:Python标准库中的一个模块,提供了HTTP客户端的功能。requests
:一个第三方库,简化了HTTP请求的发送和响应的处理。urllib
:Python标准库中的一个模块,提供了解析URL和发送请求的功能。
示例代码如下:
import requests
# 发送GET请求
response = requests.get('http://example.com')
# 检查响应状态码
if response.status_code == 200:
# 处理响应内容
print(response.text)
else:
print("请求失败,状态码:", response.status_code)
5.基于 poplib 和 smtplib 的网络编程
在Python中,poplib
和smtplib
是两个用于处理电子邮件的库,它们分别用于与POP3和SMTP服务器交互。
示例代码
使用poplib检索邮件:
import poplib
# 连接到POP3服务器
pop_server = 'pop.example.com'
username = 'your_username'
password = 'your_password'
pop3 = poplib.POP3(pop_server)
pop3.user(username)
pop3.pass_(password)
# 列出邮件
num_messages = len(pop3.list()[1])
for i in range(num_messages):
print(pop3.retr(i+1))
# 断开连接
pop3.quit()
使用smtplic发送邮件
import smtplib
from email.mime.text import MIMEText
# 创建SMTP对象并连接
smtp_server = 'smtp.example.com'
username = 'your_username'
password = 'your_password'
smtp_obj = smtplib.SMTP(smtp_server)
smtp_obj.starttls() # 启动TLS
smtp_obj.login(username, password)
# 创建邮件内容
msg = MIMEText('Hello, this is a test email.')
msg['Subject'] = 'Test Email'
msg['From'] = 'your_email@example.com'
msg['To'] = 'recipient_email@example.com'
# 发送邮件
smtp_obj.sendmail('your_email@example.com', 'recipient_email@example.com', msg.as_string())
# 断开连接
smtp_obj.quit()
四、并行计算:进程、线程和协程
1.思维导图
2.并发处理概述
- 进程是操作系统中正在执行的不同应用程序的一个实例
- 线程是进程中的一个实体,是被操作系统独立调度和分派处理器时间的基本单位
- 线程的优缺点
并发处理,因而特别适合需要同时执行多个操作的场合
解决用户响应性能和多任务的问题
引入了资源共享和同步等问题
- 协程(Coroutine)又称微线程、纤程,协程不是进程或线程,其执行过程更类似于函数调用
3.基于线程的并发处理(使用Threading库)
3.1使用Thread对象创建线程
通过创建Thread的对象可以创建线程:
Thread(target=None, name=None, args=(), kwargs={}) #构造函数
通过调用Thread对象的start方法可以启动线程。Thread对象的常用方法如下。
- t.start():启动线程。
- t.is_alive():判断线程是否活动。
- t.name:属性:线程名。对应于老版本的方法getname()和setname()。
- t.id:返回线程标识符。
threading模块包含以下若干实用函数。
- threading.get_ident():返回当前线程的标识符。
- threading.current_thread():返回当前线程。
- threading.active_count():返回活动的线程数目。
- threading.enumerate():返回活动线程的列表。
代码示例:
import threading, time, random
def timer(interval):
for i in range(3):
time.sleep(random.choice(range(interval))) #随机睡眠interval秒
thread_id = threading.get_ident() #获取当前线程标识符
print('Thread:{0} Time:{1}'.format(thread_id, time.ctime()))
if __name__=='__main__':
t1 = threading.Thread(target=timer, args=(5,)) #创建线程
t2 = threading.Thread(target=timer, args=(5,)) #创建线程
t1.start(); t2.start() #启动线程
4.基于进程的并行计算(使用multiprocessing标准库)
创建和使用进程
multiprocessing模块包含以下若干实用函数。
- cpu_count():可用的CPU核数量。
- current_process():返回当前进程。
- active_children():活动的子进程。
- log_to_stderr():函数可设置输出日志信息到标准错误输出(默认为控制台)
代码示例
import time, random
import multiprocessing as mp
def timer(interval):
for i in range(3):
time.sleep(random.choice(range(interval))) #随机睡眠interval秒
pid = mp.current_process().pid #获取当前进程ID
print('Process:{0} Time:{1}'.format(pid, time.ctime()))
if __name__=='__main__':
p1 = mp.Process(target=timer, args=(5,)) #创建进程
p2 = mp.Process(target=timer, args=(5,)) #创建进程
p1.start(); p2.start() #启动线程
p1.join(); p2.join()
5.基于asyncio的异步IO编程(asyncio标准库)
- 通过async关键字定义一个异步函数,调用异步函数返回一个协程(coroutine)对象。协程也是一种对象,协程不能直接运行,需要把协程加入到事件循环中,由后者在适当的时候调用协程
- 使用asyncio.get_event_loop()方法可以创建一个事件循环对象,然后使用其run_until_complete()方法将协程注册到事件循环
- 在异步函数中,可以使用await关键字,针对耗时的操作(例如网络请求、文件读取等IO操作)进行挂起
代码示例如下:
import asyncio, time
async def do_some_work(n): #使用async关键字定义异步函数
print('等待:{}秒'.format(n))
await asyncio.sleep(n) #休眠一段时间
return '{}秒后返回结束运行'.format(n)
start_time = time.time() #开始时间
coro = do_some_work(2)
loop = asyncio.get_event_loop()
loop.run_until_complete(coro)
print('运行时间: ', time.time() - start_time)