Python基础知识,Python大模型学习笔记

Python

安装Python:

# 下载源文件
wget https://www.python.org/ftp/python/3.12.6/Python-3.12.6.tgz

# 解压 
tar -zxvf Python-3.12.6.tgz
cd Python-3.12.6

# 编译
./configure --prefix=/root/training/Python-3.6.5
make
make install

# 添加环境变量
vim ~/.bashrc

# openssl
make  clean
./configure --prefix=/data/software/python3 --with-openssl=/data/software/openssl --with-openssl-rpath=auto

工具和镜像:

Pip:https://pip.pypa.io/en/stable/installation/

镜像地址:https://mirrors.huaweicloud.com/pythonhttps://registry.npmmirror.com/binary.html?path=python/3.11.4/

1.命令行

常用的 Python 3 命令行工具和选项:

  • python3,用途:运行 Python 脚本。python3 your_script.py。
  • -m,运行库模块作为脚本,python3 -m http.server 8000 启动一个简单的 HTTP 服务器。
  • -c,执行一段 Python 代码,python3 -c "print('Hello, World!')"。
  • -i,交互式解释器,执行完命令后保持交互模式,python3 -i。
  • -v,输出 Python 解释器启动时的版本和版权信息,python3 -v。
  • -V,输出 Python 解释器的版本,python3 -V。
  • -O,优化模式,移除文档字符串,python3 -O your_script.py。
  • -OO,进一步优化,移除文档字符串并进行一些优化,python3 -OO your_script.py。
  • -B,在执行前不写入 __pycache__ 目录,python3 -B your_script.py。
  • --check,检查源文件中的语法错误,python3 -m py_compile your_script.py。
  • -W,控制警告消息的显示,python3 -W all your_script.py。
  • -I,在交互模式下不导入 sys 和 site 模块,python3 -I。
  • -E,在执行前忽略环境变量,python3 -E your_script.py。
  • -x,在执行前忽略源文件编码声明,python3 -x your_script.py。
  • -u,强制 Python 以非缓冲的方式运行,python3 -u your_script.py。
  • -S,在执行前不导入 site.py,python3 -S your_script.py。
  • -R,在执行前不运行 site.py 中的 site.main(),python3 -R your_script.py。
  • -E,在执行前不设置 PYTHON* 环境变量,python3 -E your_script.py。
  • -X,启用或禁用特定的警告,python3 -X faulthandler your_script.py。
  • --help,显示命令行选项的帮助信息,python3 --help。

2.基础知识

Python 中有一些全局常量和变量,它们是内置的,可以在任何地方使用,而不需要导入任何模块。

常量:

  • True:布尔类型中的真值。
  • False:布尔类型中的假值。
  • None:表示空值或无值的状态。

内置类型:

  • bool:布尔类型。
  • int:整数类型。
  • float:浮点数类型。
  • complex:复数类型。
  • str:字符串类型。
  • list:列表类型。
  • tuple:元组类型。
  • dict:字典类型。
  • set:集合类型。
  • frozenset:不可变集合类型。
  • bytes:字节串类型。
  • bytearray:可变字节串类型。
  • memoryview:内存视图类型。

内置函数:

  • abs():绝对值。
  • all():判断给定的可迭代参数 iterable 中的所有元素是否都为 True。
  • any():判断给定的可迭代参数 iterable 中是否至少有一个元素为 True。
  • ascii():返回对象的 ASCII 表示。
  • bin():返回整数的二进制表示。
  • bool():将值转换为布尔类型。
  • bytearray():返回可变的字节串。
  • bytes():返回不可变的字节串。
  • callable():判断对象是否可调用。
  • chr():将 ASCII 码转为对应的字符。
  • classmethod():创建一个类方法。
  • compile():编译源代码为可执行的代码或字节码。
  • complex():返回一个复数。
  • delattr():删除对象的属性。
  • dict():返回一个新的字典。
  • dir():返回对象的属性列表。
  • divmod():返回商和余数。
  • enumerate():返回枚举对象,结合索引和元素。
  • eval():执行字符串中的 Python 表达式。
  • exec():执行字符串中的 Python 代码。
  • filter():过滤序列,过滤掉不符合条件的元素。
  • float():将值转换为浮点数。
  • format():格式化字符串。
  • frozenset():返回一个不可变集合。
  • getattr():获取对象的属性。
  • globals():返回当前全局符号表的字典。
  • hasattr():判断对象是否有指定的属性。
  • hash():返回对象的哈希值。
  • help():返回对象的帮助文档。
  • hex():返回整数的十六进制表示。
  • id():返回对象的唯一标识符。
  • input():获取用户输入。
  • int():将值转换为整数。
  • isinstance():判断对象是否是给定类型的实例。
  • issubclass():判断一个类是否是另一个类的子类。
  • iter():返回对象的迭代器。
  • len():返回对象的长度。
  • list():返回一个新的列表。
  • locals():返回当前局部符号表的字典。
  • map():对序列的每个元素应用函数。
  • max():返回最大值。
  • memoryview():返回内存视图。
  • min():返回最小值。
  • next():返回迭代器的下一个元素。
  • object():返回一个新对象。
  • oct():返回整数的八进制表示。
  • open():打开文件。
  • ord():返回字符的 ASCII 码。
  • pow():返回 x 的 y 次幂。
  • print():打印输出。
  • property():创建一个属性。
  • range():返回一个整数序列。
  • repr():返回对象的官方字符串表示。
  • reversed():反转序列。
  • round():四舍五入。
  • set():返回一个新的集合。
  • setattr():设置对象的属性。
  • slice():返回一个切片对象。
  • sorted():返回排序后的列表。
  • staticmethod():创建一个静态方法。
  • str():将值转换为字符串。
  • sum():返回序列的总和。
  • super():返回对象的父类。
  • tuple():返回一个新的元组。
  • type():返回对象的类型。
  • vars():返回对象的 dict 属性。
  • zip():将多个迭代器压缩在一起。

内置异常:

  • BaseException:所有内置异常的基类。
  • Exception:常规异常的基类。
  • ArithmeticError:所有算术错误异常的基类。
  • AssertionError:断言错误。
  • AttributeError:属性错误。
  • EOFError:文件结束错误。
  • FloatingPointError:浮点错误。
  • GeneratorExit:生成器退出异常。
  • ImportError:导入模块失败。
  • IndentationError:缩进错误。
  • IndexError:索引错误。
  • KeyError:键错误。
  • KeyboardInterrupt:键盘中断。
  • LookupError:查找错误。
  • MemoryError:内存错误。
  • NameError:名称错误。
  • NotImplementedError:未实现错误。
  • OSError:操作系统错误。
  • OverflowError:溢出错误。
  • RecursionError:递归错误。
  • ReferenceError:引用错误。
  • RuntimeError:运行时错误。
  • StopIteration:停止迭代。
  • SyntaxError:语法错误。
  • SystemError:系统错误。
  • SystemExit:系统退出。
  • TypeError:类型错误。
  • ValueError:值错误。
  • ZeroDivisionError:除零错误。

内置模块:

  • __name__:当前模块的名称。
  • __file__:当前模块的文件路径。
  • __builtins__:内置函数和变量的字典。
常量
在Python中,虽然没有专门的语法来声明常量,但按照惯例,常量名称通常使用全大写字母来表示。在Python中,任何不可变的数据类型都可以用来作为字典(map)的键。由于常量通常是不变的,所以它们可以作为字典的键。

3.基本语法

三元运算:

# 三元运算符
max_num = num1 if num1 >= num2 else num2

base_path = (
    user_path
    / format_file_name(kwargs.get("naming", "{create}_{desc}"), aweme_data_dict)
    if kwargs.get("folderize")
    else user_path
)

条件语句:使用 if, elif, else 进行条件判断。

if x > 0:
    print("Positive")
elif x == 0:
    print("Zero")
else:
    print("Negative")

循环:for 循环用于遍历序列(如列表、元组、字典等),while 循环用于在满足条件时重复执行代码块。

range() 函数在 Python 中返回的是一个 range 类型的对象。range 类型是一个不可变的序列,它提供了一种高效的方式来迭代一系列数字。range() 函数有三个参数:start(起始值,默认为 0),stop(结束值,不包含此值),和 step(步长,默认为 1)。你可以使用 step 参数来指定步长。

# for循环
for i in range(5):
    print(i)

# while循环
counter = 0
while counter < 5:
    print("counter 的值为:", counter)
    counter += 1  # 等同于 counter = counter + 1
提示
在 Python 中,break 语句只能用来退出最内层的循环。与某些其他编程语言不同,Python 不支持直接使用标签或指定层级来跳出多层嵌套循环。

遍历元组:

my_tuple = (1, 2, 3, 4, 5)

# 直接遍历
for item in my_tuple:
    print(item)

# 使用 enumerate() 遍历索引和元素
for index, item in enumerate(my_tuple):
    print(index, item)

遍历列表:

my_list = [1, 2, 3, 4, 5]

# 直接遍历
for item in my_list:
    print(item)

# 使用 enumerate() 遍历索引和元素
for index, item in enumerate(my_list):
    print(index, item)

遍历字典:

my_dict = {'a': 1, 'b': 2, 'c': 3}

# 遍历键
for key in my_dict:
    print(key)

# 遍历值
for value in my_dict.values():
    print(value)

# 遍历键值对
for key, value in my_dict.items():
    print(key, value)

合并字典:

dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}

# 使用解包语法合并
merged_dict = {**dict1, **dict2}

dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}

# 使用 update() 方法合并
dict1.update(dict2)

4.异常和错误处理

在 Python 中,异常处理是通过使用 try 和 except 语句来实现的。

try:
    result = 10 / 0
    raise ValueError("这是一个错误")
except ExceptionType1:
    # 处理 ExceptionType1 的代码块
    pass
except (ExceptionType2, ExceptionType3) as e:
    # 同时处理 ExceptionType2 和 ExceptionType3 的代码块
    print(e)
except ZeroDivisionError:
    print("不能除以零!")
    raise  # 重新抛出当前捕获的异常
except ZeroDivisionError:
    print("不能除以零!")
    raise  # 重新抛出当前捕获的异常
except Exception as e:
    print(f"发生了异常:{e}")
    raise  # 抛出新的异常或重新抛出当前捕获的异常
else:
    print("没有异常发生")
finally:
    print("这是 finally 块,总是被执行")

5.字符串操作

创建字符串:

s1 = 'Hello, World!'
s2 = "Hello, World!"
s3 = '''Hello,
World!'''
s4 = """Hello,
World!"""

字符串连接:

greeting = "Hello, "
name = "World"
message = greeting + name + "!"
print(message)  # 输出:Hello, World!

字符串重复:

repeated = "hello " * 3
print(repeated)  # 输出:hello hello hello

字符串切片:

s = "Hello, World!"
print(s[0:5])  # 输出:Hello
print(s[7:])   # 输出:World!

字符串方法:

  • .upper():转换为大写。
  • .lower():转换为小写。
  • .capitalize():首字母大写。
  • .title():每个单词的首字母大写。
  • .strip():移除字符串开头和结尾的空白字符。
  • .split():按照指定分隔符切分字符串。
  • .join():将序列中的元素以指定的字符连接生成一个新的字符串。
  • .find() 或 .index():查找子字符串并返回索引位置。
  • .replace():替换字符串中的某些字符。
  • .len():返回字符串长度。

字符串格式化:

name = "World"
greeting = "Hello, %s!" % name
print(greeting)  # 输出:Hello, World!

greeting = "Hello, {}!".format(name)
print(greeting)  # 输出:Hello, World!

greeting = f"Hello, {name}!"
print(greeting)  # 输出:Hello, World!

字符串编码:

s = "Hello, World!"
encoded = s.encode('utf-8')  # 编码为字节串
decoded = encoded.decode('utf-8')  # 解码为字符串

字符串前缀:

  • f或 F:表示格式化字符串字面量(f-string),允许在字符串中直接嵌入表达式。
  • r 或 R:表示原始字符串,忽略字符串中的转义字符。
  • b 或 B:表示字节字符串,用于处理二进制数据。

6.模块和包

Python 模块是包含 Python 代码的文件,通常是一个 .py 文件。模块可以定义函数、类和变量,也可以包含可执行的代码。

# 导入模块
import mymodule
mymodule.greet("Alice")

# 导入特定的功能
from mymodule import greet, Calculator

greet("Bob")
calculator = Calculator()

# 使用别名
import mymodule as mm
mm.greet("Charlie")

包是包含多个模块的目录,它必须包含一个名为 __init__.py 的文件(可以为空),该文件标识该目录为 Python 包。

mypackage/
│
├── __init__.py
├── module1.py
└── module2.py
__init__.py 文件可以包含初始化代码,这些代码会在导入包时自动执行。如果想在导入包时能够直接访问子模块中的内容,可以在 __init__.py 文件中显式导入这些子模块。这样,当导入包时子模块也会被自动加载。

引入包中的模块:

# 包中指定的模块
from mypackage import module1
module1.foo() 

# 这样引入,每次使用都得指定全名
import e.e1.module_1

# 引入子包
from e.e1 import module_1 
module_1.func_1()

# 相对导入
from . import module_1
访问权限
公共成员是模块的一部分,可以被模块外部的代码访问和使用。在 Python 中,任何不在变量名、函数名或类名前加前缀 _ 的成员都被认为是公共的。

特殊的文件名

  • __main__.py 文件是一个特殊的文件,它允许项目目录被直接作为模块运行。

7.元组、列表、字典

元组是一个不可变的序列,一旦创建就不能被修改。

# 创建
my_tuple = (1, 2, 3)
empty_tuple = ()

# 访问
print(my_tuple[1])  # 输出:2

# 切片
print(my_tuple[1:3])  # 输出:(2, 3)

# 解包
a, b, c = my_tuple

列表是一个可变的序列,可以修改、添加或删除其中的元素。

# 创建
my_list = [1, 2, 3]
empty_list = []

# 访问
print(my_list[1])  # 输出:2

# 切片
print(my_list[1:3])  # 输出:[2, 3]

# 添加
my_list.append(4)

# 删除
my_list.remove(2)
last_item = my_list.pop()

字典是一个无序的键值对集合,键必须是不可变类型,如字符串或元组。

# 创建
my_dict = {'name': 'Alice', 'age': 25}
empty_dict = {}

# 访问
print(my_dict['name'])  # 输出:Alice

#删除
del my_dict['age']
removed_item = my_dict.pop('gender')

集合(Set)是一个无序的、不包含重复元素的集合。它类似于数学中的集合概念,可以进行数学上的集合运算,如并集、交集、差集等。集合是一个可变的数据类型,其元素是唯一的。

# 创建
my_set = {1, 2, 3}
my_set = set([1, 2, 3])

# 使用大括号 {} 创建空集合是无效的,因为空集在 Python 中用 set() 函数表示。

# 添加元素
my_set.add(4)

# 删除元素
my_set.remove(2)
my_set.discard(5)  # 即使 5 不存在,也不会报错

# 清空集合
my_set.clear()

# 是否存在
print(3 in my_set)  # 输出:True

# 集合的大小
print(len(my_set))

# 交集
set1 = {1, 2, 3}
set2 = {3, 4, 5}
union_set = set1.union(set2)  # 或者 set1 | set2

# 差集
difference_set = set1.difference(set2)  # 或者 set1 - set2

推导式(Comprehension)是 Python 中的一种语法结构,它提供了一种简洁的方式来创建列表、字典、集合等数据结构。

# 列表推导式
[expression for item in iterable if condition]

squares = [x**2 for x in range(10)]
print(squares)  # 输出:[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
  • expression:对每个元素进行的操作。
  • item:从 iterable 中依次取出的元素。
  • iterable:一个序列、集合或其他迭代器。
  • condition(可选):一个布尔表达式,只有满足条件的元素才会被包括在内。
# 字典推导式
{key_expression: value_expression for item in iterable if condition}

squares_dict = {x: x**2 for x in range(10)}
print(squares_dict)  # 输出:{0: 0, 1: 1, 2: 4, 3: 9, ...}
  • key_expression:字典的键。
  • value_expression:字典的值。

8.函数

闭包是在一个函数内部定义的另一个函数,内部函数引用了外部函数的变量。在外部函数返回内部函数时,会形成一个闭包,因为内部函数携带了外部函数的上下文,即使外部函数已经执行完毕。

def outer_function(x):
    def inner_function(y):
        return x + y
    return inner_function

# 创建一个闭包
closure = outer_function(2)

# 使用闭包
print(closure(3))  # 输出:5

函数内使用外部变量:

x = 10  # 全局变量

def my_function():
    y = 5  # 局部变量
    print(x)  # 可以访问全局变量

my_function()

在 Python 中,所有的参数传递都是按引用传递。然而,由于 Python 中的数字、字符串和元组等是不可变类型,所以当它们作为参数传递给函数时,表现得像是按值传递。

  • 不可变类型(按值传递):如果参数是不可变类型,对参数的修改不会影响原始数据。
  • 可变类型(按引用传递):如果参数是可变类型(如列表、字典等),则可以在函数内部修改它们,并且这些修改会影响到原始数据。
global
在函数外部定义的变量默认是全局变量,但在函数内部定义的变量默认是局部变量。如果你想在函数内部修改全局变量,你需要使用 global 关键字来声明。

函数参数可以通过多种方式传递给函数。以下是一些常见的参数传递方式:

# 位置参数
def func(a, b, c):
    print(a, b, c)

func(1, 2, 3)  # 输出: 1 2 3

# 关键字参数
def func(a, b, c):
    print(a, b, c)

func(a=1, b=2, c=3)  # 输出: 1 2 3
func(c=3, a=1, b=2)  # 输出: 1 2 3

# 默认参数
def func(a, b, c=0):
    print(a, b, c)

func(1, 2)        # 输出: 1 2 0
func(1, 2, 3)     # 输出: 1 2 3

# 可变参数
def func(*args):
    for arg in args:
        print(arg, end=' ')

func(1, 2, 3)  # 输出: 1 2 3

# 关键字可变参数
def func(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

func(a=1, b=2, c=3)  # 输出: a: 1 b: 2 c: 3
提示
函数内可以直接使用全局变量的值,如果需要在函数内部修改全局变量的值,必须使用 global 关键字,直接修改的话,会报错:UnboundLocalError。
提示
if 代码块并不引入新的作用域,而是属于其所在的函数或模块的作用域。在 if 代码块中声明的变量,可以在整个函数或模块中访问。
解包
在 Python 中,如果你有一个字典,其中的键和值分别对应函数的参数名和参数值,你可以使用 ** 操作符将字典拆解为单独的参数来调用函数

_(下划线)是一个特殊的变量名,通常用于表示一个临时变量或者一个不需要使用的值。 

def some_function():
    return 42

# 调用函数但忽略返回值
_ = some_function()

 _ = asyncio.create_task(sleep())

9.面向对象

Python 是一种支持面向对象编程(Object-Oriented Programming, OOP)的高级编程语言。面向对象编程是一种编程范式,它使用“对象”来设计应用程序和程序的结构。

类(Class):

  • 类是创建对象的模板或蓝图。它定义了一组属性(变量)和方法(函数)。
  • 类可以包含构造器(__init__),这是一个特殊的方法,当创建类的新实例时会自动调用。
class Car:
    def __init__(self, make, model):
        self.make = make
        self.model = model

对象(Object):

  • 对象是类的实例。创建类的新实例时,会创建一个对象。
  • 对象可以接收数据(即类的属性)和执行操作(即类的方法)。
my_car = Car("Toyota", "Corolla")

继承(Inheritance):

  • 继承是一种创建新类的方式,新类可以从现有类中继承属性和方法。
  • 子类(派生类)继承父类(基类)的特性,并可以添加或覆盖它们。
class ElectricCar(Car):
    def __init__(self, make, model, battery_size):
        super().__init__(make, model)
        self.battery_size = battery_size

封装(Encapsulation):

  • 封装是将数据(属性)和代码(方法)捆绑在一起的过程,并对对象的某些部分隐藏起来,只暴露有限的接口。
  • 在 Python 中,可以通过在属性名前加双下划线(__)来实现属性的私有化。
class Car:
    def __init__(self, make, model):
        self.__make = make
        self.__model = model

多态(Polymorphism):

  • 多态性是指允许不同类的对象对同一消息做出响应的能力,即同一个接口,使用不同的实例而执行不同操作。
  • 在 Python 中,多态可以通过方法重载和重写来实现。
class Car:
    def start(self):
        print("Car is starting")

class ElectricCar(Car):
    def start(self):
        print("Electric Car is starting with no noise")

属性(Attributes):

  • 属性是对象的状态信息,即对象的变量。
  • 属性可以是公有的,也可以是私有的。
动态设置属性值
如果想通过内置方法动态设置对象的属性,可以使用setattr函数。setattr是一个内置函数,可以用来设置对象的属性值。setattr(object, name, value)

方法(Methods):

  • 方法是对象的行为,即对象可以执行的操作。
  • 方法通常用来修改对象的状态或执行与对象相关的操作。

类变量和实例变量:

  • 类变量是定义在类中的变量,所有实例共享同一个类变量。
  • 实例变量是定义在方法中的变量,每个实例都有自己的实例变量。

类方法和静态方法:

  • 类方法不接收隐式的 self 参数,而是接收 cls 作为第一个参数,它是属于类的,而不是实例的。
  • 静态方法不接收 self 或 cls 参数,它们可以不依赖于对象或类直接被调用。
class MyClass:
    class_variable = "I am a class variable"  # 类变量

    def __init__(self, value):
        self.instance_variable = value  # 实例变量

    @staticmethod
    def static_method():
        print("I am a static method")

特殊方法:

  • __init__(self, ...): 类的构造器,当一个实例被创建时调用。
  • __del__(self): 类的析构器,当一个实例被销毁时调用。
  • __call__(self, ...): 允许一个实例像函数那样被调用。
  • __getitem__(self, key): 获取序列的元素,如 obj[key]。
  • __setitem__(self, key, value): 设置序列的元素,如 obj[key] = value。
  • __delitem__(self, key): 删除序列的元素,如 del obj[key]。
  • __len__(self): 返回容器中元素的数量,如 len(obj)。
  • __iter__(self): 返回对象的迭代器,用于迭代操作,如 for x in obj。
  • __next__(self): 返回迭代器的下一个元素。
  • __repr__(self): 返回对象的“官方”字符串表示,通常用于调试。
  • __str__(self): 返回对象的“非官方”字符串表示,用于打印。
  • __bytes__(self): 返回对象的字节串表示。
  • __format__(self, format_spec): 定义对象的格式化字符串表示。
  • __lt__(self, other), __le__(self, other), __eq__(self, other), __ne__(self, other), __gt__(self, other), __ge__(self, other): 定义对象的比较操作。
  • __hash__(self): 返回对象的哈希值。
  • __bool__(self): 定义布尔值测试。
  • __getattr__(self, name): 当访问一个不存在的属性时调用。
  • __setattr__(self, name, value): 当设置一个属性的值时调用。
  • __delattr__(self, name): 当删除一个属性时调用。
  • __getattribute__(self, name): 在访问属性之前调用,可以重写以拦截属性访问。
  • __dir__(self): 返回对象的属性目录。
  • __enter__(self), __exit__(self, exc_type, exc_value, traceback): 用于定义上下文管理器,如 with obj。
  • __copy__(self), __deepcopy__(self, memo): 用于定义对象的浅拷贝和深拷贝行为。
  • __new__(cls, ...): 创建并返回类的新实例。

10.多线程

Python 多线程是指在 Python 程序中同时运行多个线程的能力。线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。

10.1 常用方法

Python 提供了 threading 模块来支持多线程编程。

  • threading.Thread 类:用于创建线程。可以通过继承 Thread 类并重写其 run() 方法来定义线程任务。
    start() 方法:启动线程。必须在 Thread 实例上调用此方法以开始线程的执行。
  • join() 方法:阻塞调用它的线程,直到线程终止。这通常用于等待线程完成其任务。
  • is_alive() 方法:返回线程是否仍然存活(即正在运行或等待)。
  • getName() 方法:返回线程的名称。
  • setName() 方法:设置线程的名称。
  • current_thread() 函数:返回当前线程的 Thread 实例。
  • enumerate() 函数:返回一个列表,包含当前活动的线程。
  • active_count() 函数:返回当前活动线程的数量。
  • Lock 类:用于线程同步的锁。可以用于保护共享资源,避免竞争条件。
  • RLock 类:可重入锁。它允许同一个线程多次获得锁。
  • Semaphore 类:信号量。用于限制对共享资源的访问数量。
  • BoundedSemaphore 类:有界信号量。与 Semaphore 类似,但初始化时需要指定一个最大值。
  • Event 类:事件。用于线程间的通信,允许一个线程通知其他线程某个事件已经发生。
  • Condition 类:条件变量。用于复杂的线程同步,允许一个或多个线程等待,直到被另一个线程通知。
  • Barrier 类:屏障。用于多线程同步,使得一组线程相互等待,直到到达某个共同点。
  • Timer 类:计时器。在指定的时间后执行一个函数。
  • local 和 stack_local 类:用于创建线程局部数据。
  • ThreadError 异常:当线程操作出错时抛出的异常。
  • settrace() 函数:设置一个全局的线程追踪函数。
  • setprofile() 函数:设置一个全局的线程分析函数。

10.2 创建线程

常用示例:

import threading

class MyThread(threading.Thread):
    def __init__(self, name):
        threading.Thread.__init__(self)
        self.name = name

    def run(self):
        print(f"Thread {self.name} is running")

# 创建线程
t1 = MyThread(name="Thread-1")
t2 = MyThread(name="Thread-2")

# 启动线程
t1.start()
t2.start()

# 等待线程结束
t1.join()
t2.join()

常用示例:

def run_in_thread(thread_id):
    # 创建一个新的事件循环
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    # 运行协程
    loop.run_until_complete(my_coroutine(thread_id))
    loop.close()

# 启动线程
thread = threading.Thread(target=run_in_thread, args=(1,))

10.3 线程Lock

线程同步是确保多个线程在访问共享资源时避免数据不一致和竞态条件的重要机制。Python 提供了多种同步原语,如锁(Lock)、事件(Event)、条件(Condition)和信号量(Semaphore)等。

锁(Lock),锁是最基本的同步原语,用于确保同一时间只有一个线程可以执行某个代码段:

# 创建锁
import threading
lock = threading.Lock()

# 使用 .acquire() 方法获取锁。如果锁已被其他线程获取,则当前线程将阻塞,直到锁被释放。
lock.acquire()

# 释放锁
lock.release()

# Lock 对象可以作为上下文管理器使用,确保在离开代码块时自动释放锁
with lock:
    # 执行临界区代码
    pass

# 尝试获取锁,如果锁已经被其他线程获取,则立即返回 False 而不是等待。
if lock.try_acquire():
    try:
        # 执行临界区代码
        pass
    finally:
        lock.release()

# .acquire(timeout=...) 方法可以设置超时时间,如果在指定的时间内无法获取锁,则抛出 TimeoutError。
try:
    lock.acquire(timeout=5)
except threading.TimeoutError:
    print("Could not acquire lock within the timeout period")

10.4 线程Event

Event(事件) ,事件用于线程之间的通信,一个线程可以等待事件被另一个线程设置:

import threading

event = threading.Event()

def waiter():
    event.wait()
    print("Event is set")

def setter():
    print("Waiting for 5 seconds...")
    threading.sleep(5)
    event.set()

t1 = threading.Thread(target=waiter)
t2 = threading.Thread(target=setter)

t1.start()
t2.start()

t1.join()
t2.join()

10.5 线程Condition

Condition,条件变量用于复杂的线程同步,允许一个或多个线程等待,直到被另一个线程通知:

import threading

c = threading.Condition()

def consumer():
    with c:
        print("Consumer is waiting for data")
        c.wait()
        print("Consumer received data")

def producer():
    with c:
        print("Producer is producing data")
        c.notify()
        print("Data produced")

t1 = threading.Thread(target=consumer)
t2 = threading.Thread(target=producer)

t1.start()
t2.start()

t1.join()
t2.join()

11.with语句

with 语句在 Python 中是一种语法结构,它用于包裹执行代码块,以确保资源的正确管理,特别是在处理文件操作、线程锁和其他需要设置和清除资源的场合。

  • 当执行到 with 语句时,Python 会调用上下文管理器的 __enter__ 方法,并且通常会将 __enter__ 方法的返回值赋值给 as 后面的变量。
  • 执行 with 代码块内的代码。
  • 代码块执行完成后,无论是否发生异常,都会调用上下文管理器的 __exit__ 方法。如果发生异常,__exit__ 方法的参数会接收到异常的类型、值和 traceback 对象,否则这些参数都是 None。
# 文件操作
with open('file.txt', 'r') as file:
    data = file.read()
    # 文件会在此处自动关闭

# 线程锁
lock = threading.Lock()
with lock:
    # 执行临界区代码
    pass
# 锁会在此处自动释放

# 上下文管理器
class ManagedResource:
    def __enter__(self):
        print("Entering context.")
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("Exiting context.")
        # 可以在这里处理异常
with ManagedResource() as resource:
    # 使用资源
    pass

12.asyncio  

在 Python 3.4 版本中,asyncio 模块被引入作为标准库,提供了异步编程的支持。

  • 从 Python 3.5 开始,async 和 await 关键字被引入,使得编写异步代码更加直观和简洁。
  • Python 3.7 版本进一步优化了 asyncio,引入了 asyncio.run() 这样的高级方法,让编写和管理异步程序变得更加简单。
  • asyncio 是 Python 的一个标准库,用于编写单线程并发代码,基于事件循环。

事件循环(Event Loop):

  • 事件循环是 asyncio 的核心,它不断地执行事件和任务,直到没有更多的事件和任务为止。
  • 事件循环负责调度协程,处理 I/O 事件,执行回调函数等。

相关概念:

  • 协程(Coroutine)是 asyncio 中的基本单元,用于异步执行代码。协程可以通过 async def 定义,并使用 await 来暂停和恢复执行。
  • 任务(Task)是协程的包装器,用于将协程调度到事件循环中运行。任务提供了更多控制功能,例如取消任务、获取任务状态等。
  • Future是一个表示异步操作结果的对象。它可以被设置为完成状态,并存储一个结果或异常。Task 是 Future 的一个子类,专门用于包装协程。
在 asyncio 中,协程(Coroutine)本身只是一个可等待的对象(awaitable),它不会自动运行。协程需要被显式地调度到事件循环中(await、create_task),才会开始执行。

12.1 asyncio.run()

asyncio.run()是 Python asyncio 模块中用于运行异步程序的顶层入口函数。它负责启动事件循环、执行指定的协程,并管理整个异步程序的生命周期。

  • 启动事件循环:asyncio.run() 会创建一个新的事件循环,并将其设置为当前线程的事件循环。
  • 运行协程:它会运行传入的协程,直到协程完成。
  • 清理资源:在协程运行完成后,asyncio.run() 会关闭事件循环,并清理相关资源。
  • 确保线程安全:它确保在一个线程中只能运行一个事件循环,避免并发问题。
import asyncio

async def main():
    print("Hello")
    await asyncio.sleep(1)
    print("World")

asyncio.run(main())
asyncio.run() 是一个顶层入口函数,用于启动事件循环并运行一个协程。根据其设计,asyncio.run() 不能在同一个线程中被调用多次。

12.2 协程和任务管理

12.21 asyncio.gather()

asyncio.gather() 可以并发运行多个协程,并等待它们全部完成。

import asyncio

async def task1():
    await asyncio.sleep(1)
    return "Task 1 done"

async def task2():
    await asyncio.sleep(2)
    return "Task 2 done"

async def main():
    results = await asyncio.gather(task1(), task2())
    print(results)

asyncio.run(main())

12.22 asyncio.wait_for(aw, timeout)

为协程或任务设置超时时间。如果超时,会引发 asyncio.TimeoutError。

import asyncio

async def long_running_task():
    await asyncio.sleep(10)
    return "Done"

async def main():
    try:
        result = await asyncio.wait_for(long_running_task(), timeout=5)
        print(result)
    except asyncio.TimeoutError:
        print("Task timed out")

asyncio.run(main())

12.23 asyncio.create_task(coro)

将协程封装为任务,并将其添加到事件循环中。

import asyncio

async def say_hello():
    await asyncio.sleep(1)
    print("Hello")

async def main():
    task = asyncio.create_task(say_hello())
    await task

asyncio.run(main())

在 asyncio 中,协程(coroutine)和任务(task)是两个密切相关但又有所区别的概念。它们在异步编程中扮演不同的角色,适用于不同的场景。

协程(Coroutine)是 Python 中的一种特殊函数,使用 async def 定义。它是一个可暂停和恢复执行的函数,通常用于异步操作。

  • 定义异步逻辑:协程用于定义异步操作,例如网络请求、文件 I/O 等。
  • 并发执行:多个协程可以并发运行,但需要通过事件循环来调度。
  • 嵌套调用:协程可以嵌套调用其他协程,形成复杂的异步逻辑。

任务(Task)是 asyncio 中的一个高级概念,用于封装协程,并将其添加到事件循环中。任务是协程的包装器,提供了更多的控制功能,例如取消任务、获取任务状态等。

  • 显式任务管理:当你需要显式管理协程的执行时,使用任务。例如,取消任务、获取任务状态等。
  • 并发任务:多个任务可以并发运行,任务会自动被事件循环调度。
  • 任务优先级:虽然 asyncio 默认不支持任务优先级,但可以通过自定义逻辑实现。
协程用于定义异步逻辑,任务用于管理协程的执行。

12.3 事件循环管理

12.31 asyncio.get_running_loop()

获取当前正在运行的事件循环,在协程中获取事件循环对象

import asyncio

async def main():
    loop = asyncio.get_running_loop()
    print(loop)

asyncio.run(main())

12.32 asyncio.get_event_loop()

获取当前线程的事件循环,手动管理事件循环

import asyncio

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.sleep(1))

12.7 asyncio.set_event_loop(loop)

设置当前线程的事件循环。

import asyncio

loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)

12.33 asyncio.new_event_loop()

创建一个新的事件循环

import asyncio

loop = asyncio.new_event_loop()

12.4 同步原语

12.41 asyncio.Event()

创建事件对象,用于任务间的同步,协程可以等待事件被设置。

import asyncio

async def waiter(event):
    print("Waiting for event")
    await event.wait()
    print("Event set")

async def setter(event):
    await asyncio.sleep(2)
    event.set()

async def main():
    event = asyncio.Event()
    await asyncio.gather(waiter(event), setter(event))

asyncio.run(main())

12.42 asyncio.Lock()

用于任务间的互斥锁,防止多个任务同时访问共享资源。

import asyncio

async def worker(lock):
    async with lock:
        print("Worker acquired lock")
        await asyncio.sleep(1)

async def main():
    lock = asyncio.Lock()
    await asyncio.gather(worker(lock), worker(lock))

asyncio.run(main())

12.43 asyncio.Semaphore

asyncio.Semaphore 基于异步上下文管理器(Async Context Manager)实现,是一个用于控制并发数量的同步原语。可以限制同时运行的协程(coroutine)的数量,从而避免资源竞争或过度消耗系统资源。

import asyncio

# 创建一个 Semaphore,允许同时运行 5 个协程
semaphore = asyncio.Semaphore(5)

async def worker(name):
    async with semaphore:  # 获取 Semaphore
        print(f"Worker {name} is starting")
        await asyncio.sleep(1)  # 模拟耗时操作
        print(f"Worker {name} is done")

async def main():
    tasks = [worker(i) for i in range(10)]  # 创建 10 个任务
    await asyncio.gather(*tasks)  # 并发运行所有任务

# 运行主函数
asyncio.run(main())

12.5 asyncio.sleep(delay)

异步等待指定的时间。

import asyncio

async def main():
    print("Hello")
    await asyncio.sleep(1)
    print("World")

asyncio.run(main())

12.6 asyncio.run_in_executor(executor, func, *args)

在指定的执行器(线程池或进程池)中运行阻塞函数。

import asyncio
from concurrent.futures import ThreadPoolExecutor

def blocking_task():
    print("Blocking task started")
    time.sleep(2)
    print("Blocking task finished")

async def main():
    with ThreadPoolExecutor() as pool:
        await asyncio.get_event_loop().run_in_executor(pool, blocking_task)

asyncio.run(main())

12.7 Async Context Manager

异步上下文管理器(Async Context Manager)是 asyncio 异步编程中的一种高级特性,用于管理异步资源的生命周期。它允许你在异步代码中使用 async with 语法,类似于同步代码中的 with 语句,从而确保资源在使用前后正确地初始化和清理。

在异步编程中,资源的获取和释放可能涉及异步操作(例如,打开和关闭网络连接、文件操作等)。传统的同步上下文管理器(通过 with 语句)无法处理这些异步操作,因为它们不能在 __enter__ 和 __exit__ 方法中使用 await。异步上下文管理器通过定义 __aenter__ 和 __aexit__ 方法来支持异步操作。

import asyncio

class AsyncFile:
    def __init__(self, filename):
        self.filename = filename

    async def __aenter__(self):
        print(f"Opening file: {self.filename}")
        self.file = open(self.filename, 'w')
        return self.file

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        print(f"Closing file: {self.filename}")
        self.file.close()

async def main():
    async with AsyncFile("example.txt") as file:
        file.write("Hello, world!\n")
        await asyncio.sleep(1)

asyncio.run(main())

12.8 协程上下文数据

在 Python 中,协程确实有上下文的概念,可以通过 contextvars 模块来管理协程的上下文。contextvars 模块提供了一组接口,可用于在协程中管理、设置、访问局部上下文的状态。

import contextvars
import asyncio

class Context:
    _context = contextvars.ContextVar('context', default={})

    @classmethod
    def set(cls, key, value):
        context = cls._context.get()
        context[key] = value
        cls._context.set(context)

    @classmethod
    def get(cls, key):
        context = cls._context.get()
        return context.get(key)

# 示例协程
async def inner():
    value = Context.get('key')
    print(f'Inner: {value}')
    await asyncio.sleep(1)

async def outer():
    Context.set('key', 'value')
    print(f'Outer: {Context.get("key")}')
    await inner()

# 运行协程
asyncio.run(outer())

contextvars 模块的上下文变量是基于调用链的。当你在父协程中设置一个上下文变量时,这个变量的值会被传递到所有从该父协程调用的子协程中。并且每个协程都有自己的上下文副本。当子协程调用 Context.set(key, value) 时,它只会修改其自身的上下文副本,而不会影响父协程的上下文。

Python 的 contextvars 模块中,上下文变量的行为可以总结如下:

子协程不设置值:

  • 如果子协程没有设置上下文变量的值,那么它会继承父协程的上下文变量值。
  • 在子协程中获取上下文变量的值时,将返回父协程设置的值。

子协程设置了值:

  • 如果子协程设置了上下文变量的值,那么它会覆盖继承自父协程的值。
  • 在子协程及其后续调用的协程中获取上下文变量的值时,将返回子协程设置的值。
  • 父协程的上下文变量值不会被影响。

13.json处理

Python数据转Json:

import json

# 一个 Python 字典
data = {
    "name": "John",
    "age": 30,
    "city": "New York"
}

# 输出到文件
json_str = json.dump(data, file)

# 转换为 JSON 字符串
json_str = json.dumps(data)

Json转字典:

import json

# 一个 JSON 字符串
json_str = '{"name": "John", "age": 30, "city": "New York"}'

# 解析为 Python 字典
data = json.loads(json_str)

14.日期与时间

datetime 模块是 Python 标准库中处理日期和时间的核心模块。它提供了以下类:

  • datetime.date:表示日期(年、月、日)。
  • datetime.time:表示时间(时、分、秒、微秒)。
  • datetime.datetime:表示日期和时间。
  • datetime.timedelta:表示两个日期或时间之间的差异。
  • datetime.tzinfo:所有时区信息类的基类。
  • datetime.timezone:用于表示固定时区偏移量的类。

常用函数和方法

  • date.today():返回当前本地日期。
  • datetime.now():返回当前日期和时间。
  • datetime.utcnow():返回当前的 UTC 日期和时间。
  • datetime.combine(date, time):将日期和时间合并为一个 datetime 对象。
  • datetime.strptime(date_string, format):根据指定的格式将字符串解析为 datetime 对象。
  • datetime.strftime(format):将 datetime 对象格式化为字符串。

time 模块提供了各种与时间相关的函数,主要用于处理时间戳。

  • time.time():返回当前时间的时间戳。
  • time.sleep(seconds):暂停执行指定的秒数。
  • time.localtime([secs]):根据给定的时间戳返回本地时间的 struct_time 对象。
  • time.gmtime([secs]):根据给定的时间戳返回 UTC 时间的 struct_time 对象。
  • time.mktime(tuple):将 struct_time 对象转换为时间戳。

calendar 模块提供了生成日历的功能和一些与日历相关的函数。

  • calendar.month(year, month):返回一个多行字符串,显示一个月的日历。
  • calendar.monthcalendar(year, month):返回一个列表,包含一个月中的每一天是星期几。
  • calendar.monthrange(year, month):返回一个月的第一天是星期几和该月的天数。
from datetime import datetime

# 获取当前日期和时间
now = datetime.now()

# 格式化日期和时间
formatted_date = now.strftime("%Y-%m-%d %H:%M:%S")
print("格式化后的日期和时间:", formatted_date)

# 时间戳格式化输出

import time
from datetime import datetime

# 获取当前时间的时间戳
timestamp = time.time()

# 将时间戳转换为日期时间对象
dt_object = datetime.fromtimestamp(timestamp)
print("时间戳转日期时间:", dt_object)

# 也可以使用 utcfromtimestamp() 来获取 UTC 时间
dt_utc = datetime.utcfromtimestamp(timestamp)
print("UTC 时间戳转日期时间:", dt_utc)

# 字符串转时间戳

from datetime import datetime

# 日期时间字符串
date_string = "2024-05-29 12:30:45"

# 将字符串解析为日期时间对象
dt_object = datetime.strptime(date_string, "%Y-%m-%d %H:%M:%S")

# 将日期时间对象转换为时间戳
timestamp = dt_object.timestamp()
print("字符串转时间戳:", timestamp)

15.获取指定数据的类型

# 获取不同类型的数据类型
number = 10
string = "Hello, World!"
list_data = [1, 2, 3]
dict_data = {'key': 'value'}
tuple_data = (1, 2, 3)
set_data = {1, 2, 3}
frozenset_data = frozenset([1, 2, 3])
bool_value = True

# 使用 type() 函数获取类型
print(type(number))          # <class 'int'>
print(type(string))          # <class 'str'>
print(type(list_data))       # <class 'list'>
print(type(dict_data))       # <class 'dict'>
print(type(tuple_data))      # <class 'tuple'>
print(type(set_data))        # <class 'set'>
print(type(frozenset_data))  # <class 'frozenset'>
print(type(bool_value))      # <class 'bool'>

16.文件和目录

  • os.remove(file),删除指定文件
  • os.listdir(path): 列出指定路径下的所有文件和目录名。
  • os.mkdir(path): 创建一个新目录。
  • os.makedirs(path): 创建新目录,如果中间的目录不存在也会一并创建。
  • os.rmdir(path): 删除一个空目录。
  • os.removedirs(path): 删除目录及其所有内容。
  • os.path.exists(path): 检查指定路径是否存在。
  • os.path.isfile(path): 检查指定路径是否为文件。
  • os.path.isdir(path): 检查指定路径是否为目录。
  • os.path.join(path, *paths): 将多个路径组合成一个路径。
  • os.path.getsize(path): 获取文件的大小。
  • os.path.basename(path): 获取路径的基本名称。
  • os.path.dirname(path): 获取路径的目录名称。
  • os.rename(src, dst): 重命名文件或目录。

17.正则

Python 中的正则表达式(Regular Expressions,简称 regex)是通过一些特殊字符组成的模式,用于匹配字符串中的字符组合。正则表达式在 Python 中通过内置的 re 模块提供支持

import re

# match 从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
match_result = re.match(r'^(d{4})-(d{2})-(d{2})$', '2023-11-15')  # 匹配日期格式
if match_result:
    print("Match:", match_result.groups())

# search 扫描整个字符串,并返回第一个成功的匹配。
search_result = re.search(r'^(d{4})-(d{2})-(d{2})$', '15-11-2023 is not a date')  # 搜索日期格式
if search_result:
    print("Search:", search_result.groups())

# findall 在字符串中找到正则表达式所匹配的所有子串,并返回一个列表。
all_matches = re.findall(r'bw+b', 'The rain in Spain')  # 找出所有单词
print("Find all:", all_matches)

# finditer 与 findall() 类似,返回一个迭代器,迭代器的每个元素都是一个 Match 对象。
all_matches_iter = re.finditer(r'bw+b', 'The rain in Spain')
for match in all_matches_iter:
    print("Find iter:", match.group())

# sub 替换字符串中的某些部分。
replaced_text = re.sub(r'bw+b', 'word', 'The rain in Spain')  # 替换所有单词为'word'
print("Replaced text:", replaced_text)

# subn 替换字符串中的某些部分,并返回替换的次数。
replaced_text_and_count = re.subn(r'bw+b', 'word', 'The rain in Spain')
print("Replaced text and count:", replaced_text_and_count)

# split 按照能够匹配的子串将字符串分割后返回列表。
split_text = re.split(r's+', 'The rain in Spain')  # 使用一个或多个空格分割字符串
print("Split text:", split_text)

# compile 用于编译正则表达式,生成一个正则表达式( Pattern )对象,供其他方法使用。
pattern = re.compile(r'bw+b')
match_result = pattern.match('The rain in Spain')
print("Compiled match:", match_result.group())

# escape 用于对字符串中所有可能被解释为正则运算符的字符进行转义。
escaped_string = re.escape('https://example.com?search=Python regular expressions')
print("Escaped string:", escaped_string)

# purge 清除正则表达式缓存。
re.purge()

18.数据结构

Queue 模块(先进先出(FIFO)队列)提供了多种队列类,这些类主要用于实现线程安全的队列操作,常用于多线程编程中。

import queue
from collections import deque

# 使用 queue.Queue
q = queue.Queue()
q.put(1)
q.put(2)
print(q.get())  # 输出 1
print(q.get())  # 输出 2

# 使用双端队列 collections.deque
dq = deque()
dq.append(1)
dq.appendleft(2)
print(dq.pop())  # 输出 1
print(dq.popleft())  # 输出 2
协程里不能使用会阻塞线程的函数,会中断事件循环

asyncio.Queue 是 Python asyncio 模块提供的一个异步队列类,用于在异步程序中实现生产者-消费者模式。

  • __init__(maxsize=0),初始化一个队列实例。maxsize 参数指定队列的最大容量,默认为 0,表示无限制。
  • put(item),将一个元素放入队列。如果队列已满,会等待直到有空间可用。
  • get(),从队列中取出一个元素。如果队列为空,会等待直到有元素可用。
  • task_done(),标记一个任务完成。通常在处理完一个任务后调用,用于 join() 方法。
  • join(),等待队列中的所有任务完成。会阻塞调用它的协程,直到所有任务都被标记为完成。
  • empty(),检查队列是否为空。返回 True 表示队列为空,False 表示队列不为空。
  • full(),检查队列是否已满。返回 True 表示队列已满,False 表示队列未满。只有在设置了 maxsize 时才有效。
  • qsize(),返回队列中元素的数量。

19.装饰器

装饰器是 Python 中一个非常强大且实用的特性,它允许你在不修改函数或方法源代码的情况下,增加函数或方法的额外功能。装饰器本质上是一个函数,它接收一个函数作为参数,并返回一个新的函数。

19.1装饰器的基本结构

一个简单的装饰器通常包含以下几个部分:

  • 装饰器函数:这是最外层的函数,它接收一个函数作为参数。
  • 内部包装函数:这是装饰器内部定义的函数,它负责调用原始函数,并在调用前后添加额外的逻辑。
def my_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()

运行上述代码后,输出结果为:

Something is happening before the function is called.
Hello!
Something is happening after the function is called.

19.2带参数的装饰器

装饰器也可以接收参数。这种情况下,装饰器本身需要再嵌套一层函数。带参数的装饰器定义:

  • repeat 是一个装饰器工厂函数,它接收一个参数 times。
  • decorator 是一个装饰器函数,它接收一个函数 func 作为参数。
  • wrapper 是一个内部函数,它在调用 func 时根据 times 参数重复调用多次。
def repeat(times):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            for _ in range(times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(times=3)
def say_hello(name):
    print(f"Hello, {name}!")

say_hello("Alice")
@functools.wraps(func) 是 Python 中 functools 模块提供的一个装饰器,用于在定义装饰器时保留被装饰函数的元信息(如函数名、文档字符串等)。

Pip使用方法

1.基础命令

相关地址:https://mirrors4.tuna.tsinghua.edu.cn/help/pypi/

pip和pip3的区别
pip 和 pip3 都是 Python 的包管理工具,用于安装和管理 Python 包。它们的主要区别在于它们默认关联的 Python 版本。

相关命令:

# 安装最新的包
pip3 install package_name

# 安装指定版本的包
pip3 install package_name==version

# 卸载包
pip3 uninstall package_name

# 安装指定文件内的包
pip install -r requirements.txt 

# 查看已安装
pip3 list

# 查看指定包的安装信息
pip3 show funasr

#列出当前虚拟环境中安装的所有包及其版本号,并以 requirements.txt 格式输出。
pip freeze > requirements.txt

2.其它包管理

PDM:https://github.com/pdm-project/pdm

PipEnv:https://pipenv.pypa.io/en/latest/

小技巧

1.判断是否具有指定属性

# 检查实例是否具有属性a
if hasattr(my_instance, 'a'):
    print("实例具有属性a")
else:
    print("实例不具有属性a")

2.python中的 “==”

在 PHP 中,"5" == 5 返回 true 是因为 PHP 在比较时会进行类型转换(type juggling),这意味着当你比较一个字符串和一个整数时,PHP 会尝试将字符串转换为整数,如果字符串的内容可以被解释为一个有效的整数,那么比较就会基于它们的数值进行。

Python 的比较行为与 PHP 不同,它在比较不同类型的值时不会自动进行类型转换。在 Python 中,字符串和整数是不同的数据类型,它们在比较时不会自动转换为彼此。

Python中的 == 是全等于判断

3.列表追加元素

  • Python获取数组的长度,使用len函数
  • Python数组追加元素,使用数组对象的append方法

4.字典合并

update() 方法可以将一个字典的内容更新到另一个字典中。如果两个字典有相同的键,那么键的值会被覆盖。

dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}

dict1.update(dict2)
print(dict1)  # 输出: {'a': 1, 'b': 3, 'c': 4}

从 Python 3.5 开始,可以使用 ** 操作符来合并字典。这种方法不会修改原字典,而是返回一个新的字典。

dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}

merged_dict = {**dict1, **dict2}
print(merged_dict)  # 输出: {'a': 1, 'b': 3, 'c': 4}

字典推导式可以用来合并字典,同时可以进行一些额外的处理。

dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}

merged_dict = {k: v for d in [dict1, dict2] for k, v in d.items()}
print(merged_dict)  # 输出: {'a': 1, 'b': 3, 'c': 4}

5.列表合并

+ 操作符可以用来合并两个列表,返回一个新的列表。

list1 = [1, 2, 3]
list2 = [4, 5, 6]

merged_list = list1 + list2
print(merged_list)  # 输出: [1, 2, 3, 4, 5, 6]

extend() 方法可以将一个列表的内容添加到另一个列表的末尾。这种方法会修改原列表。

list1 = [1, 2, 3]
list2 = [4, 5, 6]

list1.extend(list2)
print(list1)  # 输出: [1, 2, 3, 4, 5, 6]

列表推导式可以用来合并列表,同时可以进行一些额外的处理。

list1 = [1, 2, 3]
list2 = [4, 5, 6]

merged_list = [item for sublist in [list1, list2] for item in sublist]
print(merged_list)  # 输出: [1, 2, 3, 4, 5, 6]

6.map 函数 

map 函数是一个内置的高阶函数,它允许你将一个函数应用于一个或多个可迭代对象的每个元素,并返回一个新的可迭代对象(通常是 map 对象)。这个过程称为映射(mapping),因为函数被映射到每个元素上。

map(function, iterable, ...)
  • function:一个函数,它将被应用到可迭代对象的每个元素上。
  • iterable:一个或多个可迭代对象(如列表、元组、字符串等)。

map 函数返回一个 map 对象,它是一个迭代器。你可以通过 list()、tuple() 等函数将其转换为具体的列表或元组。

numbers = [1, 2, 3, 4, 5]

# 定义一个函数,将每个元素加 1
def add_one(x):
    return x + 1

# 使用 map 函数
result = map(add_one, numbers)

# 将 map 对象转换为列表
result_list = list(result)
print(result_list)  # 输出: [2, 3, 4, 5, 6]

7.判断字典是否有某个键

in 关键字可以用来检查字典中是否存在某个键。

my_dict = {'a': 1, 'b': 2, 'c': 3}

# 检查字典中是否存在键 'b'
if 'b' in my_dict:
    print("字典中存在键 'b'")
else:
    print("字典中不存在键 'b'")

get() 方法可以用来检查字典中是否存在某个键。如果键存在,返回对应的值;如果键不存在,返回 None 或者指定的默认值。

my_dict = {'a': 1, 'b': 2, 'c': 3}

# 检查字典中是否存在键 'b'
if my_dict.get('b') is not None:
    print("字典中存在键 'b'")
else:
    print("字典中不存在键 'b'")

8.判断列表是否有某个值

in 关键字可以用来检查列表中是否存在某个值。

my_list = [1, 2, 3, 4, 5]

# 检查列表中是否存在值 3
if 3 in my_list:
    print("列表中存在值 3")
else:
    print("列表中不存在值 3")

count() 方法可以用来检查列表中某个值出现的次数。如果次数大于 0,说明列表中存在该值。

my_list = [1, 2, 3, 4, 5]

# 检查列表中是否存在值 3
if my_list.count(3) > 0:
    print("列表中存在值 3")
else:
    print("列表中不存在值 3")

9.值类型和引用类型

在 Python 中,可变对象赋值给另一个变量时,是引用赋值,而不是值赋值。这意味着两个变量会指向同一个对象,对其中一个变量的修改会影响到另一个变量。

值类型

  • 整数(int):不可变,赋值时创建新的对象。
  • 浮点数(float):不可变,赋值时创建新的对象。
  • 字符串(str):不可变,赋值时创建新的对象。
  • 元组(tuple):不可变,赋值时创建新的对象。

引用类型

  • 列表(list):可变,赋值时创建引用,修改会影响原对象。
  • 字典(dict):可变,赋值时创建引用,修改会影响原对象。
  • 集合(set):可变,赋值时创建引用,修改会影响原对象。
  • 对象(object):可变,赋值时创建引用,修改会影响原对象。

引用类型实现值赋值,即创建一个新的对象,可以使用以下方法:

使用 copy() 方法:

a = [1, 2, 3]
b = a.copy()
b.append(4)
print(a)  # 输出:[1, 2, 3]
print(b)  # 输出:[1, 2, 3, 4]

使用切片:

a = [1, 2, 3]
b = a[:]
b.append(4)
print(a)  # 输出:[1, 2, 3]
print(b)  # 输出:[1, 2, 3, 4]
如果字典中包含嵌套的可变对象(如列表或字典),并且你希望创建一个完全独立的副本(深拷贝),可以使用 copy 模块的 deepcopy 方法。

10.urlcode编解码

使用 quote 函数对 URL 中的特定部分进行编码。它会将非 ASCII 字符和特殊字符转换为 % 加两位十六进制数字的形式。

from urllib.parse import quote

# 需要编码的字符串
url_part = "你好,世界!"
encoded_url_part = quote(url_part)

print(encoded_url_part)  # 输出:%E4%BD%A0%E5%A5%BD%EF%BC%8C%E4%B8%96%E7%95%8C%EF%BC%81

如果需要对整个 URL 进行编码,可以使用 urlencode 函数。它通常用于将参数字典转换为查询字符串并进行编码。

from urllib.parse import urlencode

# 参数字典
params = {
    "name": "张三",
    "age": 25,
    "city": "北京"
}

# 将参数字典转换为查询字符串并编码
encoded_query = urlencode(params)

print(encoded_query)  # 输出:name=%E5%BC%A0%E4%B8%89&age=25&city=%E5%8C%97%E4%BA%AC

使用 unquote 函数对编码后的 URL 进行解码,将 % 加两位十六进制数字的形式还原为原始字符。

from urllib.parse import unquote

# 编码后的 URL 部分
encoded_url_part = "%E4%BD%A0%E5%A5%BD%EF%BC%8C%E4%B8%96%E7%95%8C%EF%BC%81"
decoded_url_part = unquote(encoded_url_part)

print(decoded_url_part)  # 输出:你好,世界!

如果需要将编码后的查询字符串解码并转换为参数字典,可以使用 parse_qs 函数。

from urllib.parse import parse_qs

# 编码后的查询字符串
encoded_query = "name=%E5%BC%A0%E4%B8%89&age=25&city=%E5%8C%97%E4%BA%AC"

# 解码查询字符串并转换为参数字典
decoded_params = parse_qs(encoded_query)

print(decoded_params)  # 输出:{'name': ['张三'], 'age': ['25'], 'city': ['北京']}

Python虚拟环境(venv)

Python虚拟环境是一个独立的Python解释器和库的副本。它允许您在不影响系统全局Python安装的情况下安装和管理项目特定的包。

1.创建虚拟环境

# 建一个名为venv的虚拟环境
python3 -m venv venv

这将在项目目录中创建一个名为venv的文件夹,其中包含您的虚拟环境。您可以将该文件夹命名为其他名称,但通常将其命名为venv是一个很好的做法。

2.激活虚拟环境

激活虚拟环境将确保您在该环境中安装的包和运行的Python命令是隔离的。

# 在Unix或macOS上
source venv/bin/activate

# 在Windows上
.venv\Scripts\activate.bat

# 激活虚拟环境后,您的终端或命令提示符将显示虚拟环境的名称
(venv) $

3.退出虚拟环境

# 退出虚拟环境
deactivate

FastAPI

FastAPI:https://fastapi.tiangolo.com/zh/ 

1.获取请求参数

获取 GET 参数:

from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/items/")
async def read_query_item(q: str = Query(...)):
    return {"q": q}

Form 用于从 application/x-www-form-urlencoded 或 multipart/form-data 编码的请求体中获取数据,通常用于处理表单提交的数据。以下是 Form 支持的参数:

  • default: 设置参数的默认值。
  • min_length: 字符串的最小长度。
  • max_length: 字符串的最大长度。
  • regex: 字符串必须匹配的正则表达式。
  • required: 指定字段是否为必填项,默认为 True。

获取POST参数:

from fastapi import FastAPI, Form

app = FastAPI()

@app.post("/items/")
async def create_item(name: str = Form(...), price: float = Form(...)):
    return {"name": name, "price": price}

Query 用于从 URL 的查询字符串中获取数据。它支持以下参数:

  • default: 设置参数的默认值。
  • alias: 为参数设置一个别名,这在 URL 中使用的名称与函数参数名称不一致时非常有用。
  • title: 为参数设置一个标题,这通常用于 API 文档。
  • description: 为参数提供一个描述,这在 API 文档中显示,有助于说明参数的用途。
  • gt (greater than): 参数值必须大于指定的值。
  • lt (less than): 参数值必须小于指定的值。
  • ge (greater than or equal to): 参数值必须大于或等于指定的值。
  • le (less than or equal to): 参数值必须小于或等于指定的值。
  • min_length: 参数的最小长度(对于字符串)。
  • max_length: 参数的最大长度(对于字符串)。
  • regex: 参数值必须匹配指定的正则表达式。
  • example: 为参数提供一个示例值,这在 API 文档中显示。

获取JSON参数:

from fastapi import FastAPI

app = FastAPI()

@app.post("/items/")
async def create_item(item: dict):
    return {"item": item}

2.Request对象

Request 对象代表了进入应用的 HTTP 请求。

from fastapi import FastAPI, Request

app = FastAPI()

@app.get("/items/")
async def read_items(request: Request):
    query_param = request.query_params("query")  # 获取查询参数
    headers = request.headers  # 获取请求头
    body = await request.json()  # 获取 JSON 请求体
    return {"query_param": query_param, "headers": dict(headers), "body": body}

3.Response 对象

Response 对象用于构建和返回 HTTP 响应。

from fastapi import FastAPI, Response

app = FastAPI()

@app.get("/items/")
async def read_items(response: Response):
    content = {"item": "some item"}
    response.headers["X-Custom-Header"] = "Value"  # 设置响应头
    response.status_code = 200  # 设置状态码
    return response  # 返回 Response 对象

4.校验JSON参数

在 FastAPI 中,当你在路径操作函数中声明一个参数,并将其类型指定为 Pydantic 模型时,FastAPI 会自动将请求体解析为 JSON 并进行验证。

from fastapi import FastAPI
from pydantic import BaseModel

class Item(BaseModel):
    name: str
    description: str = None
    price: float
    tax: float = None

app = FastAPI()

@app.post("/items/")
async def create_item(item: Item):
    return {"name": item.name, "description": item.description}

5.FastApi事件

from fastapi.exceptions import RequestValidationError
from starlette.exceptions import HTTPException as StarletteHTTPException

# 请求参数异常
@app.exception_handler(RequestValidationError)
async def request_validation_error(request: Request, exc: RequestValidationError):
    print(exc.errors())
    return JSONResponse(status_code=200, content={"code": 0, "msg": 'error occur'})


# HTTP请求出现异常错误
@app.exception_handler(StarletteHTTPException)
async def request_validation_error(request: Request, exc: StarletteHTTPException):
    return JSONResponse(status_code=200, content={"code": 0, "msg": exc.detail})

# 应用启动
@app.on_event("startup") 

# 应用关闭
@app.on_event("shutdown")

Python项目

1.收集

收集一些很厉害的Python仓库:

大模型:

实用库:

大模型平台

网络请求:

相关名词

  • U2-Net是由Xuebin Qin等人开发的一种用于显著目标检测(Salient Object Detection, SOD)的深度学习模型。
  • ONNXRuntime是由微软推出,用于优化和加速机器学习推理和训练,适用于ONNX模型,是一个跨平台推理和训练机器学习加速器(ONNX Runtime is a cross-platform inference and training machine-learning accelerator)
  • Rembg和U2-Net之间的关系是工具与核心算法的关系,Rembg利用U2-Net作为其图像分割的引擎。

开源地址:

16k、32k这些参数的区别?

对于那本长篇小说,128k模型几乎可以记住整本书的内容。所以,无论你问到小说的哪个部分,它都能给出非常详细和准确的回答。

简单来说,这些数字(16k、32k、128k)代表了AI模型的“记忆力”。记忆力越强,模型在处理长文本和复杂对话时就越出色,能够生成更加丰富和连贯的回答,以16k为例:

  • 输入:如果你给这个模型发送一段文本,它最多能记住大约16,000个单词的信息。
  • 输出:当它回复你时,它的回答将基于这16,000个单词的信息。如果你们的对话非常长,超过了这个字数,它可能就会“忘记”一些早期的信息。
  • 例子:假设你们正在讨论一本长篇小说,16k模型可能只能记住小说的一小部分内容,所以在回答关于小说结尾的问题时,它可能记不住开头的细节。

2.Rembg

Rembg 是一个基于 Python 的背景去除工具,它使用深度学习技术来从图像中去除背景。

Pytorch:https://pytorch.org/get-started/locally/

开源地址:https://github.com/danielgatis/rembg

详见Github仓库的说明:https://github.com/danielgatis/rembg

3.FunASR

FunASR是一个基础语音识别工具包,提供多种功能,包括语音识别(ASR)、语音端点检测(VAD)、标点恢复、语言模型、说话人验证、说话人分离和多人对话语音识别等。

Github:https://github.com/modelscope/FunASR/blob/main/README_zh.md#%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B

服务端部署文档:https://github.com/modelscope/FunASR/blob/main/runtime/readme_cn.md

# 安装
pip3 install torch torchvision torchaudio

# 安装
pip3 install -U funasr

4.PyTorch

PyTorch 是一个开源的机器学习库,基于 Python,主要用于深度学习研究和开发。它由 Facebook 的人工智能研究团队(FAIR)开发,并于 2016 年首次发布。

pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu120

nvidia-smi 是 NVIDIA System Management Interface 的缩写,它是 NVIDIA 提供的一个命令行工具,用于管理和监控 NVIDIA GPU 设备。

nvidia-smi

CUDA(Compute Unified Device Architecture,统一计算设备架构)是 NVIDIA 推出的一种并行计算平台和编程模型,用于利用 NVIDIA GPU(图形处理单元)进行通用计算。简而言之,CUDA 允许开发者编写程序,将计算任务分配到 GPU 上执行,从而实现高性能计算。

CUDA下载:https://developer.nvidia.com/cuda-toolkit-archive

如果你已经安装了 CUDA Toolkit,可以通过以下命令查看其版本:

nvcc --version

CUDA版本和显卡驱动版本的关联:https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html#cuda-major-component-versions__table-cuda-toolkit-driver-versions 

Pytorch版本和CUDA的关联:https://pytorch.org/get-started/previous-versions/

5.Segment Anything

Github:https://github.com/facebookresearch/segment-anything