python知识体系
一、数据类型
1、原子型
定义:一种值的集合 + 定义在值集合上的一组操作
特点:无法被改变
- int
- float
- string
- boolean
字符串详解
#1.转义字符
自行查阅
#2.字符运算
如下表
#3.Python 三引号
Python 三引号允许一个字符串跨多行,字符串中可以包含换行符、制表符以及其他特殊字符。
#4.字符串内建函数
自行查阅
字符串运算
| 操作符 | 描述 | 实例 |
|---|---|---|
| + | 字符串连接 | >>>a + b ‘HelloPython’ 注意:-1 表示从右边起第一位 |
| * | 重复输出字符串 | >>>a * 2 ‘HelloHello’ |
| [] | 通过索引获取字符串中字符 | >>>a[1] ‘e’ |
| [ : : ] | 截取字符串中的一部分 | >>>a[1:4:2] ‘el’ |
| in | 成员运算符 - 如果字符串中包含给定的字符返回 True | >>>“H” in a True |
| not in | 成员运算符 - 如果字符串中不包含给定的字符返回 True | >>>“M” not in a True |
| r | 原始字符串:所有的字符串都是直接按照字面的意思来使用 | >>>print r’\n’ \n |
| % | 格式字符串 | print “My name is %s and weight is %d kg!” % (‘Zara’, 21) |
2、结构型
定义:一种数据结构 + 定义在这种数据结构上的一组操作
-
list
-
tunlp
-
set
-
dict
2.1 列表(list)详解
特点:列表是动态的, 长度大小不固定, 可以任意的增加、删除、修改
语法:[a,b,...] eg: [ 1,b ]
1、增删改
增:append(obj) | insert(index, obj)
删:remove(obj) | del(list[index]) | pop(index)
改:list[index] = newObj
2、列表长度: len(list)
2.2 元组(tunlp)详解
元组是静态的, 长度大小固定, 不能增删改
eg: ( 1,a )
2.3 集合(set)详解
集合里面的元素无序,不重复的!不支持索引
eg: { 8, 9 }
2.4 字典(dict)详解
字典是由多个键值对组成的集合,键不可重复(重复的话会被覆盖)
1、 len(dict)
2、增删改查
增:dict1[‘newKey’] = value
删:pop(‘key’, defalutValue)
改:dict1[‘key’] = newValue
查:dict1[‘key’]
3、遍历
for key, value in student.items():
二、流程控制
- if
- for
- while
- break,continue
语法:
# if
if X:
....
elif:
....
else:
....
# for
for 变量 in 序列:
语句
....
# while
while 表达式:
语句
....
三、迭代器、生成器
1、迭代器
迭代器是一个可以被遍历的对象,提供了逐个访问元素的能力(通常用 for 循环)。它遵循 迭代器协议,即实现了两个方法:
- iter():返回迭代器对象本身。
- next():返回下一个元素,遍历结束时抛出 StopIteration 异常。
通俗理解:迭代器就像一个“指针”,每次调用 next() 就指向并返回序列中的下一个元素,直到没有元素为止。
常见例子:Python 的列表、元组、字符串等可以通过 iter() 函数转为迭代器
# 创建一个列表
my_list = [1, 2, 3]
# 转为迭代器
iterator = iter(my_list)
# 使用 next() 获取元素
print(next(iterator)) # 输出: 1
print(next(iterator)) # 输出: 2
print(next(iterator)) # 输出: 3
# 遍历完后,再次调用 next() 会抛出 StopIteration
try:
print(next(iterator))
except StopIteration:
print("No more elements!")
# 用 for 循环遍历(更常用)
iterator = iter(my_list) # 重新创建迭代器
for item in iterator:
print(item) # 输出: 1, 2, 3
2、生成器
生成器是一种特殊的迭代器,它通过 yield 关键字 按需生成数据,而不是一次性将所有数据加载到内存。
通俗理解:生成器像一个“暂停和恢复”的函数,每次调用 next() 时执行到 yield 处,生成一个值并暂停,等下次调用再继续。
特点:
- 惰性计算:数据按需生成,节省内存。
- 自动实现迭代器协议(无需手动定义 iter 和 next)。
- 只能遍历一次,耗尽后需重新创建。
eg:
# 定义生成器函数:生成 1 到 n 的平方
def square_generator(n):
for i in range(1, n + 1):
yield i * i
# 创建生成器对象
gen = square_generator(3)
# 使用 next() 获取值
print(next(gen)) # 输出: 1 (1*1)
print(next(gen)) # 输出: 4 (2*2)
print(next(gen)) # 输出: 9 (3*3)
# 或者用 for 循环
#在 Python 中,for 循环会自动实现 next() 功能。
gen = square_generator(3) # 重新创建
for square in gen:
print(square) # 输出: 1, 4, 9
说明:
- yield i * i 每次生成一个平方值并暂停。
- 调用 next(gen) 或 for 循环时,函数从上一次暂停处继续执行。
- 生成器只计算当前需要的平方,节省内存
字节面试题
统计1T的nginx 访问日志文件,统计后端url访问次数,并取出前十的url及其访问次数。后端的url以 /api 开头
#生成一个生成器,读取文件
def read_log(file_path):
with open(file_path, 'r') as file:
for line in file:
yield line
#分析日志
def analysis_log(lines):
#统计nginx访问日志中url的访问次数,只统计后端接口的访问次数
#223.104.84.107 - - [18/Apr/2025:04:05:25 +0000] "POST /api/bazi/paipan HTTP/1.1" 200 226 "http://47.107.237.220/bazi" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36"
url_count = {}
for line in lines:
#取出url
url = line.split(' ')[6]
#只统计后端接口的访问次数
if url.startswith('/api/'):
url_count[url] = url_count.get(url, 0) + 1
return url_count
#统计前10的url
def analysis_top_10(url_count):
#根据url的访问次数排序,不要用语法糖
sorted_url_count = sorted(url_count.items(), key=lambda x: x[1], reverse=True)
#取前10
return sorted_url_count[:10]
def main():
file_path = 'access.log'
lines = read_log(file_path)
url_count = analysis_log(lines)
top_10 = analysis_top_10(url_count)
print(top_10)
if __name__ == "__main__":
main()
四、函数
1、 定义与使用
定义:
def fun_name(arg1,arg2):
语句
…
return value
使用:
fun_name(arg1,arg2)
2、 参数
- 必须参数
- 关键字参数
- 默认参数
- 可变参数
1. 必须参数
def test(a,b):
pass
2. 关键字参数
test(a="tmli",b=18)
3. 默认参数
def test(a,b=18):
pass
4. 可变参数
def test(*args,**kwargs):
pass
" *args " 获取的是一个元组
" **kwargs " 获取的是一个字典
3、 变量作用域
- 局部变量:仅函数内部使用
- 全局变量: 整个程序范围内使用
4、 返回值
如果想获取函数中的局部变量,可以使用return关键字返回
5、 Lambda表达式(匿名函数)
def add(x,y):
retutn x+y
lambda x,y:x+y
五、面向对象
1、定义和使用
class animal:
pass
dog=animal()
2、构造方法
class animal:
def __init__(self):
语句
类在实例化时会自动调用构造方法,用于创建新的类实例
3、类的属性,方法
属性(成员变量、类变量),必须是“self.” 的方式赋值。直接定义的变量在函数执行完就会被销毁
类里面方法的第一次参数必须是self,在构造方法中我们可以初始化一些属性:
class animal:
def __init__(self,name):
self.name=name
def eat(self):
print("eating!!!")
def main():
dog = animal("wangwang")
dog.eat()
if __name__ == "__main__":
main()
4、类的私有属性,私有方法
在类中定义变量或者函数时以双下划线开头。
私有属性和方法只能在类中使用
案例:学生类 (Student)
我们创建一个 Student 类,管理学生信息:
私有属性:__age(学生年龄,敏感数据)。
私有方法:__is_valid_age(验证年龄是否合法)。
普通方法:设置年龄 (set_age) 和获取年龄 (get_age)。
class Student:
def __init__(self, name):
self.name = name
# 私有属性:年龄
self.__age = 0
# 私有方法:验证年龄是否合法
def __is_valid_age(self, age):
return 0 < age <= 120
# 普通方法:设置年龄
def set_age(self, age):
if self.__is_valid_age(age):
self.__age = age
return f"{self.name}'s age set to {age}"
else:
return "Invalid age!"
# 普通方法:获取年龄
def get_age(self):
return f"{self.name}'s age is {self.__age}"
# 测试代码
student = Student("Bob")
print(student.set_age(20)) # 输出: Bob's age set to 20
print(student.get_age()) # 输出: Bob's age is 20
print(student.set_age(-5)) # 输出: Invalid age!
# 尝试直接访问私有属性(会报错)
try:
print(student.__age)
except AttributeError:
print("Cannot access private attribute __age directly!")
5、类方法和静态方法
1、静态方法 (staticmethod)
定义:
- 静态方法是通过 @staticmethod 装饰器定义的类方法。
- 它不接收任何隐式参数,既不接收实例(self),也不接收类(cls)。
特点:
- 无需访问实例或类的状态:静态方法不依赖于实例或类的属性/方法,因此可以独立调用。
- 调用方式:可以通过类名或实例调用,但通常通过类名调用更直观。
- 用途:通常用于定义与类相关的工具函数或逻辑,这些函数不需要访问类的状态,但从语义上与类相关。
2、类方法 (classmethod)
定义:
- 类方法是通过 @classmethod 装饰器定义的类方法。
- 它接收类本身作为第一个隐式参数,习惯命名为 cls。
- 类方法可以访问和修改类的状态(如类属性),但不能直接访问实例的属性。
特点:
- 接收类作为参数:第一个参数 cls 指向类本身,可以用来访问类属性或调用其他类方法。
- 调用方式:可以通过类名或实例调用,但通常通过类名调用更常见。
- 用途:常用于定义需要操作类状态或实现替代构造函数的场景。
eg:
class PetStore:
# 类属性:记录宠物总数
total_pets = 0
def __init__(self, name):
self.name = name
# 每添加一只宠物,总数加 1
PetStore.total_pets += 1
# 类方法:获取宠物总数
@classmethod
def get_total_pets(cls):
return f"{cls.__name__} has {cls.total_pets} pets"
# 静态方法:检查宠物名字是否合法
@staticmethod
def is_valid_name(name):
return name.strip() != ""
# 测试代码
def main():
# 使用静态方法检查名字
print(PetStore.is_valid_name("Buddy")) # 输出: True
print(PetStore.is_valid_name("")) # 输出: False
# 创建宠物
pet1 = PetStore("Buddy")
print(pet1.name) # 输出: Buddy
print(PetStore.get_total_pets()) # 输出: PetStore has 1 pets
pet2 = PetStore("Luna")
print(PetStore.get_total_pets()) # 输出: PetStore has 2 pets
if __name__ == "__main__":
main()
6、继承与多态
继承
**是什么:**本质就是在一个类的基础上定制一个新类,新类不仅可以继承父类的方法和属性,还能添加新的。python支持继承多个父类
特点:
如果子类定义了构造方法,父类的构造方法不会被调用(多态)
子类不能继承父类的私有方法,私有属性
多态
子类和父类有相同的方法时,子类方法会覆盖父类的方法
六、常见设计模式
在实际开发中,最常用的设计模式通常有以下几种:
创建型
- 单例模式:确保一个类只有一个实例,如数据库连接池、配置管理器
- 工厂方法:将对象的创建委托给专门的工厂类,隐藏具体实现细节
结构型
- 装饰器模式:动态地给对象添加功能,常见于I/O流处理、Web中间件
- 适配器模式:让不兼容的接口能够协同工作,如旧系统集成
行为型
- 观察者模式:定义对象间的一对多依赖关系,适用于事件处理系统
- 策略模式:定义算法族并封装,使它们可互换,如支付方式选择
- 迭代器模式:提供统一的方式遍历集合,不暴露内部结构
这些模式之所以常用,是因为它们解决了软件开发中反复出现的基本问题,如灵活创建对象、组织代码结构、处理对象间通信等。根据不同的编程语言和应用领域,使用频率可能有所不同。
单例模型
确保一个类只有一个实例
适用场景:数据库连接、配置管理器、日志记录器
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
#super() 获取父类引用(这里是 object,因为所有 Python 类默认继承自 object)
#super().__new__(cls) 调用 object.__new__(cls),创建一个全新的 Singleton 类实例
cls._instance = super().__new__(cls)
cls._instance.value = "单例对象的数据"
return cls._instance
# 测试
s1 = Singleton()
s2 = Singleton()
print(s1 is s2) # 输出: True
print(s1.value) # 输出: 单例对象的数据
在 Python 中,new 是一个特殊方法,主要用于控制对象的创建过程。它属于类的静态方法,在对象实例化时首先被调用,负责创建并返回一个新的对象实例
工厂方法模式
适用场景:根据条件创建不同但相关的对象
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "汪汪!"
class Cat(Animal):
def speak(self):
return "喵喵!"
class AnimalFactory:
def create_animal(self, animal_type):
if animal_type == "dog":
return Dog()
elif animal_type == "cat":
return Cat()
else:
raise ValueError(f"不支持的动物类型: {animal_type}")
# 使用工厂
factory = AnimalFactory()
dog = factory.create_animal("dog")
cat = factory.create_animal("cat")
print(dog.speak()) # 输出: 汪汪!
print(cat.speak()) # 输出: 喵喵!
装饰器模式
适用场景:在不修改原代码的情况下添加功能,如日志、缓存、权限检查
def log_decorator(func):
def wrapper(*args, **kwargs):
print(f"调用函数: {func.__name__}")
result = func(*args, **kwargs)
print(f"函数 {func.__name__} 返回: {result}")
return result
return wrapper
@log_decorator
def add(a, b):
return a + b
# 测试
result = add(3, 5) # 输出函数调用信息和结果
def wrapper(*args, **kwargs) 是 Python 中一种非常灵活的函数定义方式,允许函数接收任意数量的位置参数和关键字参数。这种语法在编写装饰器、包装函数或需要传递可变数量参数的函数时特别有用。
基本解释
*args: 收集所有位置参数到一个元组中
**kwargs: 收集所有关键字参数到一个字典中
eg:
def show_args(*args):
print(f"args 的类型是: {type(args)}")
print(f"args 的内容是: {args}")
# 可以像处理元组一样处理 args
for i, arg in enumerate(args):
print(f"第 {i+1} 个参数是: {arg}")
# 调用函数,传入多个位置参数
show_args(10, "hello", [1, 2, 3])
###
args 的类型是: <class 'tuple'>
args 的内容是: (10, 'hello', [1, 2, 3])
第 1 个参数是: 10
第 2 个参数是: hello
第 3 个参数是: [1, 2, 3]
###
def show_kwargs(**kwargs):
print(f"kwargs 的类型是: {type(kwargs)}")
print(f"kwargs 的内容是: {kwargs}")
# 可以像处理字典一样处理 kwargs
for key, value in kwargs.items():
print(f"参数 '{key}' 的值是: {value}")
# 调用函数,传入多个关键字参数
show_kwargs(name="Alice", age=30, city="Beijing")
###
kwargs 的类型是: <class 'dict'>
kwargs 的内容是: {'name': 'Alice', 'age': 30, 'city': 'Beijing'}
参数 'name' 的值是: Alice
参数 'age' 的值是: 30
参数 'city' 的值是: Beijing
###
适配器模式
让不兼容的接口能够协同工作,如旧系统集成
# 已有的接口
class OldSystem:
def old_request(self, string):
return f"旧系统处理: {string}"
# 目标接口
class NewSystem:
def new_request(self, data):
pass
# 适配器
class SystemAdapter(NewSystem):
def __init__(self, old_system):
self.old_system = old_system
def new_request(self, data):
# 转换请求格式
result = self.old_system.old_request(data)
return f"适配后的结果: {result}"
# 使用
old = OldSystem()
adapter = SystemAdapter(old)
result = adapter.new_request("测试数据")
print(result) # 输出: 适配后的结果: 旧系统处理: 测试数据
观察者模式
定义对象间的一对多依赖关系,适用于事件处理系统
适用场景:事件处理系统、消息推送
class Subject:
def __init__(self):
self._observers = []
self._state = None
def attach(self, observer):
self._observers.append(observer)
def notify(self):
for observer in self._observers:
observer.update(self._state)
#将方法转换为只读属性
#允许使用 subject.state 语法访问 _state 值,不需要调用方法(不用写括号)
@property
def state(self):
return self._state
#定义当属性被赋值时执行的代码
#允许使用 subject.state = value 语法设置值
#在设置状态值的同时自动调用 notify() 通知所有观察者
@state.setter
def state(self, value):
self._state = value
self.notify()
class Observer:
def update(self, state):
pass
class ConcreteObserver(Observer):
def __init__(self, name):
self.name = name
def update(self, state):
print(f"观察者 {self.name} 收到通知: 状态变为 {state}")
# 使用
subject = Subject()
observer1 = ConcreteObserver("观察者1")
observer2 = ConcreteObserver("观察者2")
subject.attach(observer1)
subject.attach(observer2)
subject.state = "新状态"
# 输出:
# 观察者 观察者1 收到通知: 状态变为 新状态
# 观察者 观察者2 收到通知: 状态变为 新状态
虽然两个方法都叫 state,但它们有不同的功能:
@property 装饰的 state 方法:处理读取操作
@state.setter 装饰的 state 方法:处理写入操作
七、装饰器
看了那么多篇,就这篇通俗易懂,我在这里就不自己总结
https://blog.csdn.net/zhh763984017/article/details/120072425
七、异常与异常处理
1、异常
运行时检测到的错误被称为异常。通常检测到异常,程序会中断。
2、异常处理
有时候我们希望某些错误不会影响到程序的完整运行,这时候我们可以进行异常处理!
语法:
try:
业务语法块
expert 异常类型:
处理异常语法块
...
else:
无异常语法块
finally:
无论是否有异常都会执行语法块
3、抛出异常
除了系统抛出的异常,我们也可以自动抛出异常。
raise Exception("这是错误信息")
4、自定义异常
当内建的类无法满足需求是,我们需要自定义异常
自定义异常需要继承Exception
class MyException(Exception):
def __init__(self):
pass
"""
返回一个对象的描述信息,python中调用print()打印实例化对象时会调用__str__()如果__str__()中有返回值,就会打印其中的返回值。
"""
def __str__(self):
return "这是个自定义异常"
八、模块
1、模块
1.1 是什么
模块就是 定义重复利用代码的 python文件, 可用 import 或者 from…import… 导入使用
import //导入模块文件
from…import… //从指定模块文件中导入指定的函数
1.2 __ name __ 变量
模块的模块名可以通过全局变量 “__ name __ ” 获取
module.__name__ //模块module的名字
__name__ //当前模块名称,当模块被运行时模块名为“__main__”,可以用这个特性判断当前文件是被运行还是作为模块导入
1.3 dir函数
dir函数可以列出对象的 模块标识符(函数,类,变量)
print(dir(os))
2、包
2.1 是什么
包是用来管理模块的,简单来说包就是文件夹,里面必须要有__ init __.py 文件,该文件用于标识当前文件夹是一个包
2.2 包在多目录中使用
当你导入一个模块或者包的时候,python解析器对模块位置的搜索顺序是:
- 首先查找当前目录
- 如果不在当前目录,python则会搜索在shell变量PYTHONPATH下的每一个目录
- 如果都找不到,python就会查看默认路径。以linux为例,默认路径一般为/usr/local/lib
模块搜索路径存储在system模块的sys.path变量中,变量包含当前目录、PYTHONPATH下的目录、由安装过程决定的默认目录
3、标准库
python官方提供的包和模块,我们称为标准库,他会随着python解析器安装到计算机中
3.1 sys
sys模块提供了很多函数和变量来处理python运行环境的不同部分
sys.platform //识别操作系统
sys.argv //获取命令行的参数(执行脚本是传入的参数)
sys.exit //退出程序
sys.path //获取模块的搜索路径
sys.modules //找到已导入模块
扩展
- 与类和实例无绑定关系的function都属于函数(function);
- 与类和实例有绑定关系的function都属于方法(method);
3.2 os
os模块封装了操作系统的文件和目录操作。
os.getcwd //获取当前文件执行路径
os.chdir //切换当前路径
os.rename //文件重命名
os.mkdir(path) //创建目录
os.makedirs //创建多重目录
os.environ.items() //获取系统环境变量
os.path.dirname(__file__) //当前文件所在位置(__file__为内置变量,表示文件绝对路径)
os.path.exists //判断路径是否存在
os.path.isfile //判断路径是否是文件
os.path.isdir //判断路径是否是目录
3.3 math
math封装了许多运算和函数操作
3.4 random
random模块包含了很多随机数相关的方法
4、第三方库
使用pip命令管理第三方库
语法:
pip list //列出已安装软件包
pip [install/uninstall] 软件包名==版本号 //安装或卸载
pip install -r requirements.txt //批量安装
pip search 关键字
pip install 软件包名==版本号 -i 源地址
九、文件与IO
1、文件内容操作
内置函数open可以对文件内容进行处理(读,写,改)
1.1 打开文件
内置函数open打开文件, 无论是读还是写都要先打开文件
例子:
f=open(file,mode='r',encoding=None,buffering=-1)
1.2 文件基本操作
f.read() //读
f.readline() //按行读,readlines() 全部读出返回一个数组
f.write() //写
f.writelines() //按行写
1.3 关闭文件对象(close)
为了安全起见,无论是读还是写都要关闭文件对象,虽然程序结束也会自动关闭
f.close
扩展:
如果读写过程有异常,建议try捕获处理
1.4 案例
遍历日志文件的每一行(这种写法会自动帮我们关闭文件对象,不需要执行close)
with open('log.txt','r') as f:
for line in f.readlines():
print(line)
十、进程与线程
1、介绍
1.1 是什么
进程:操作系统进行资源分配的基本单位
线程:cpu运算调度的基本单位
1.2 两者之间的关系
一个进程可以有多个线程;进程中的线程可以共享该进程的全部资源
在使用python xx.py 运行时,内部就创建一个进程(主进程),在进程中创建了一个线程(主线程),由线程逐行运行代码。
1.3 CPython
CPython是最流行的python解析器。
CPython 使用了 全局解析器锁(GIL) 来实现线程同步,即任意时刻一个进程只能有一个线程被cpu执行!这样做是为了防止多个线程同时执行python字节码。因此就算多核心的cpu也禁止一个进程里面的多线程的并行,浪费了大量的cpu性能。所以可以用多进程可以充分利用cpu资源
1.4 使用场景
- 计算密集型,用多进程,例如:大量的数据计算(算法)。
- IO密集型,用多线程,例如:文件读写、网络数据传输 。
2、线程
2.1 多线程
多线程是指在操作系统上并发执行多个线程的技术。一个1核的cpu只能运行一个线程,但是操作系统可以快速切换不同的线程,由于时间间隔太小,给用户造成一种同时执行的假象!
在python中我们一般使用threading模块中的Thread类实现多线程
方法1
from threading import Thread
import time
def work(id):
print("{id} 正在工作".format(id=id))
print("{id} thread is over".format(id=id))
def main():
threads = []
# 创建线程
for i in range(5):
thread = Thread(target=work, args=(i,))
threads.append(thread)
# 启动线程
for i in range(5):
threads[i].start()
# join()方法只有等待线程执行完毕才会往下继续执行
for i in range(5):
thread[i].join()
print("end!!!!!")
if __name__ == "__main__":
main()
方法2:
from threading import Thread
import time
class mythread(Thread):
def __init__(self, id):
super(mythread, self).__init__()
self.id = id
def run(self):
print("{id} 正在工作".format(id=self.id))
time.sleep(2)
print("{id} thread is over".format(id=self.id))
def main():
threads = []
# 创建线程
for i in range(5):
thread = mythread(i)
threads.append(thread)
# 启动线程
for i in range(5):
threads[i].start()
# 等待线程执行完毕
for i in range(5):
thread.join()
print("end!!!!!")
if __name__ == "__main__":
main()
2.2 线程同步
确保每次只有一个线程在执行
from threading import Thread, Lock
import time
class mythread(Thread):
def __init__(self, id):
super(mythread, self).__init__()
self.id = id
def run(self):
# 获取锁
t_lock.acquire()
print("{id} 正在工作".format(id=self.id))
# 释放锁
t_lock.release()
t_lock.acquire()
time.sleep(2)
print("{id} thread is over".format(id=self.id))
t_lock.release()
def main():
threads = []
# 创建线程
for i in range(5):
thread = mythread(i)
threads.append(thread)
# 启动线程
for i in range(5):
threads[i].start()
# 等待线程执行完毕
for i in range(5):
thread.join()
print("end!!!!!")
if __name__ == "__main__":
t_lock = Lock()
main()
2.3 线程队列
队列可以通过控制锁(锁定、释放等)来实现线程之间的数据共享
在python中我们通常采用Queue模块实现队列功能,遵循先进先出的规则
from threading import Thread
import queue
import time
work_q = queue.Queue(maxsize=6)
result_q = queue.Queue(maxsize=6)
class myThread(Thread):
def __init__(self, id):
super(myThread, self).__init__()
self.id = id
def run(self):
while not work_q.empty():
# 从工作队列中去取数据
work = work_q.get()
out = "{id} is work".format(id=self.id)
# 模拟工作耗时
time.sleep(2)
# 将数据存进结果队列中
result_q.put(out)
def main():
# 工作队列中放入数据
for i in range(6):
work_q.put(i)
# 开启两个线程
for i in range(2):
myThread(i).start()
# 取出并输出队列的数据
for i in range(6):
print(result_q.get())
if __name__ == "__main__":
main()
3. 进程
调用外部命令也是调用进程的方式,os模块提供了许多调用外部命令的的函数,如system、exec系列函数。subprocess模块。multiprocessing.Process。
此处只讲解multiprocessing.Process实现多进程,进程同步,进程队列。
3.1 multiprocessing.Process多进程
multiprocessing实现多进程的方式和多线程相似。multiprocessing.Queue可以在多线程中进行通信,
from multiprocessing import Process, Queue
import time
class myprocess(Process):
def __init__(self, id, q):
super(Process, self).__init__()
self.id = id
self.q = q
def run(self):
print("{id} 正在工作".format(id=self.id))
time.sleep(2)
print("{id} process is over".format(id=self.id))
out = "{id} result!!!".format(id=self.id)
self.q.put(out)
def main():
result_q = Queue()
processes = []
# 创建线程
for i in range(5):
thread = myprocess(i, result_q)
processes.append(thread)
# 启动线程
for i in range(5):
processes[i].start()
# 等待线程执行完毕
for i in range(5):
processes[i].join()
while not result_q.empty():
print(result_q.get())
time.sleep(1)
if __name__ == "__main__":
main()
3.2 进程池
进程池可以提供指定数目的进程供用户使用,每当有新的请求提交到pool时,如果pool还没满,就可以创建一个新的进程来执行该请求;如果pool中的进程数已经达到规定的最大值,那么请求就会等待,直到池中有进程结束才会创建新的进程来执行它。
from multiprocessing import Pool
import time
def run(id):
print("{id} 正在工作".format(id=id))
time.sleep(2)
print("{id} process is over".format(id=id))
def main():
pool = Pool(processes=3)
# 向线程池中加入要执行的任务
for i in range(5):
pool.apply_async(run, args=(i,))
# 关闭线程池,不能再有新的任务被加入到线程池
pool.close()
# 等待所有子进程结束
pool.join()
if __name__ == "__main__":
main()
线程池可以使用multiprocess.dummp.Pool函数,使用基本和上述一致
4. 协程
协程,又称微线程。协程的作用是在执行函数A时可以随时中断去执行函数B,然后中断函数B继续执行函数A(可以自由切换)。但这一过程并不是函数调用,这一整个过程看似像多线程,然而协程只有一个线程执行。
优势:
- 执行效率极高,因为子程序切换(函数)不是线程切换,由程序自身控制,没有切换线程的开销。所以与多线程相比,线程的数量越多,协程性能的优势越明显。
- 不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在控制共享资源时也不需要加锁,因此执行效率高很多。
十一、正则表达式
十二、网络编程
十三、操作数据库
十四、爬虫
1、urllib
get请求
from urllib import request
# 创建请求类
request = request.Request("https://www.baidu.com")
#发起请求
response = request.urlopen(request)
# 用decode解码读到的内容
print(response.read().decode("utf-8"))
post请求
from urllib import request,parse
url = "http://httpbin.org/post"
headers = {
#伪装一个火狐浏览器
"User-Agent":'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)',
"host":'httpbin.org'
}
dict = {
"name":"Germey"
}
# Request传入的data必须是bytes (字节流)类型,如果是一个字典,可以先用 urlencode() 转成字符串,再用bytes()转成字节流类型
data = bytes(parse.urlencode(dict),encoding="utf8")
req = request.Request(url=url,data=data,headers=headers,method="POST")
response = request.urlopen(req)
print(response.read().decode("utf-8"))
print(response.getcode())
本文详细介绍了Python的基础数据类型,包括原子型(int、float、string、boolean)和结构型(list、tuple、set、dict)。深入探讨了字符串的运算、列表的增删改查、元组的不可变性、集合的无序和不重复以及字典的操作。此外,还讲解了迭代器和生成器的概念与使用,以及函数的定义、参数、返回值和作用域。文章提到了面向对象编程中的类定义、构造方法、属性和方法,以及继承和多态。接着,介绍了装饰器、异常处理、模块和包的使用,以及标准库如sys、os、math和random的常见功能。最后,讨论了文件I/O、进程与线程的概念、多线程同步、进程间通信,并简要提及了正则表达式、网络编程、数据库操作和爬虫的基础知识。
2964

被折叠的 条评论
为什么被折叠?



