python八股文
保留字段
def # 用于定义一个函数 if # 条件语句,用于根据条件执行代码块 elif # “else if”的简写,多个条件分支中的一个 and # 逻辑与操作符,两个操作数都为真时,结果才为真 not # 逻辑非操作符,将布尔值取反 or # 逻辑或操作符,只要任一操作数为真,结果就为真 assert # 调试工具,用于验证条件,如果条件为假,触发异常 try # 用于定义异常处理块,尝试执行代码块 exec # 动态执行 Python 代码,通常用于执行字符串或代码对象 finally # 用于定义无论是否发生异常都会执行的代码块 for # 用于迭代序列(如列表、元组、字符串)中的每个元素 in # 检查某个值是否在序列(如列表、字符串)中 break # 终止循环,即使循环条件仍为真 pass # 空操作,占位符,表示什么都不做 class # 用于定义一个类 from # 从模块中导入指定的部分 print # 输出信息到控制台(Python 2.x 中是一个关键字,Python 3.x 中是函数) continue # 跳过当前循环的剩余部分,并继续下一次循环 global # 声明在函数内使用全局变量 raise # 显式引发一个异常 return # 从函数中返回结果 del # 删除对象或变量 import # 导入模块或模块中的指定部分 while # 用于在条件为真时重复执行代码块 else # 条件语句或循环结束后执行的代码块 is # 判断两个对象是否引用自同一内存地址 with # 用于简化资源管理(如文件操作)的上下文管理器 except # 用于捕获并处理异常 lambda # 用于创建匿名函数 yield # 在生成器函数中生成值,并暂停函数的执行
def # 用于定义一个函数
if # 条件语句,用于根据条件执行代码块
elif # “else if”的简写,多个条件分支中的一个
and # 逻辑与操作符,两个操作数都为真时,结果才为真
not # 逻辑非操作符,将布尔值取反
or # 逻辑或操作符,只要任一操作数为真,结果就为真
assert # 调试工具,用于验证条件,如果条件为假,触发异常
try # 用于定义异常处理块,尝试执行代码块
exec # 动态执行 Python 代码,通常用于执行字符串或代码对象
finally # 用于定义无论是否发生异常都会执行的代码块
for # 用于迭代序列(如列表、元组、字符串)中的每个元素
in # 检查某个值是否在序列(如列表、字符串)中
break # 终止循环,即使循环条件仍为真
pass # 空操作,占位符,表示什么都不做
class # 用于定义一个类
from # 从模块中导入指定的部分
print # 输出信息到控制台(Python 2.x 中是一个关键字,Python 3.x 中是函数)
continue # 跳过当前循环的剩余部分,并继续下一次循环
global # 声明在函数内使用全局变量
raise # 显式引发一个异常
return # 从函数中返回结果
del # 删除对象或变量
import # 导入模块或模块中的指定部分
while # 用于在条件为真时重复执行代码块
else # 条件语句或循环结束后执行的代码块
is # 判断两个对象是否引用自同一内存地址
with # 用于简化资源管理(如文件操作)的上下文管理器
except # 用于捕获并处理异常
lambda # 用于创建匿名函数
yield # 在生成器函数中生成值,并暂停函数的执行
python语言的特性
动态强类型
Python的基本数据类型
- Number(数字)(包括整型、浮点型、复数、布尔型等) #不可变
- String(字符串)#不可变
- Tuple(元组) #不可变
- List(列表)#可变
- Set(集合)#可变
- Dictionary(字典)#可变
py作为后端语言的优缺点
- 优点
- 语言简单灵活,开发效率高
- 胶水语言,轮子多,拥有Django这种的成熟web框架
- 缺点
- 执行效率低,性能不如其他语言
- 动态语言,没有类型声明时就没有自动补全,而且很多问题要运行后才能发现
什么是duck type鸭子类型
鸭子类型更关注对象的行为,只要实现了某种接口方法就行,而不在乎是什么类型
monkey patch
monkey patch就是运行时替换对象,本质上是对象的重新赋值
*args,**kwargs
的作用
用来处理可变参数,接收参数后,args会变成一个tuple,kwargs会变成一个dict
CPython GIL全局锁
引入GIL是因为CPython的内存管理并不是线程安全的,
为了保护多线程下对python对象的访问,每个线程在执行过程中都需要先获取GIL,保证同一时刻只有一个线程在执行代码
GIL使得python的多线程不能充分发挥多核CPU的性能,对CPU密集型程序的影响较大
生成器
生成器是一种特殊类型的迭代器,用于逐个生成值,而不是一次性返回所有值。生成器通过使用 yield 关键字来实现,这使得它们在生成大量数据时更高效,因为生成器不会一次性将所有值存储在内存中。
生成器通常通过函数定义,并使用 yield 关键字代替 return 来返回值。每次调用生成器的 __next__()
方法(通常是通过 next()
函数或for
循环隐式调用)时,生成器函数会暂停执行,并返回当前的 yield
表达式的值。在下一次调用时,生成器会从上次暂停的地方继续执行。
生成器的使用场景
- 处理大数据: 生成器特别适合处理需要逐步生成或计算的数据,比如读取大文件、一行一行地处理数据。
- 无限序列: 生成器可以用于生成无限长的序列,比如斐波那契数列、素数序列等。
- 管道机制: 生成器可以在处理数据流时充当管道的一部分,一步一步处理数据,而不是一次性将所有数据处理完
浅拷贝和深拷贝
-
浅拷贝出来的是一个独立的对象,但它的子对象还是原对象中的子对象
-
深拷贝会递归地拷贝原对象中的每一个子对象,因此拷贝后的对象和原对象互不相关。
# 浅拷贝示范 import copy original_list = [1, 2, [3, 4]] shallow_copied_list = copy.copy(original_list) #浅拷贝 shallow_copied_list[2][0] = 'changed' print(original_list) # 输出: [1, 2, ['changed', 4]] print(shallow_copied_list) # 输出: [1, 2, ['changed', 4]]
# 浅拷贝示范
import copy
original_list = [1, 2, [3, 4]]
shallow_copied_list = copy.copy(original_list) #浅拷贝
shallow_copied_list[2][0] = 'changed'
print(original_list) # 输出: [1, 2, ['changed', 4]]
print(shallow_copied_list) # 输出: [1, 2, ['changed', 4]]
迭代器与可迭代对象的区别
-
可迭代对象类,必须自定义__iter__()魔法方法,range,list类的实例化对象都是可迭代对象
-
迭代器类,必须自定义__iter__()和__next__()魔法方法,用iter()函数可以创建可迭代对象的迭代器
my_list = [1, 2, 3] for item in my_list: # my_list 是一个可迭代对象 print(item) my_list = [1, 2, 3] my_iterator = iter(my_list) # 使用 iter() 函数从可迭代对象中获取迭代器 print(next(my_iterator)) # 输出:1 print(next(my_iterator)) # 输出:2 print(next(my_iterator)) # 输出:3 # 如果再次调用 next(my_iterator),会抛出 StopIteration 异常
my_list = [1, 2, 3]
for item in my_list: # my_list 是一个可迭代对象
print(item)
my_list = [1, 2, 3]
my_iterator = iter(my_list) # 使用 iter() 函数从可迭代对象中获取迭代器
print(next(my_iterator)) # 输出:1
print(next(my_iterator)) # 输出:2
print(next(my_iterator)) # 输出:3
# 如果再次调用 next(my_iterator),会抛出 StopIteration 异常
闭包
闭包就是一个嵌套函数,它的内部函数 使用了 外部函数的变量或参数,它的外部函数 返回了 内部函数
可以保存外部函数内的变量,不会随着外部函数调用完而销毁
python垃圾回收机制
引用计数为主,标记清除 和 分代回收为辅
引用计数机制是这样的:
-
当对象被创建,被引用,作为参数传递,存储到容器中,引用计数+1
-
当对象离开作用域,引用指向别的对象,del,从容器中移除,引用计数-1
-
当引用计数降为0,python就会自动回收该对象所在的内存空间,
-
但是引用计数无法解决循环引用的问题,所以引入了标记清除和分代回收机制
async和await的作用
- async: 声明一个函数为异步函数,函数内只要有await就要声明为async
- await: 搭配asyncio.sleep()时会切换协程,当切换回来后再继续执行下面的语句
dict查找原理
- dict底层是哈希表,哈希表类似于C语言的数组,可以实现按索引随机访问
- 但dict的key不一定是整数,需要先通过哈希函数,再经过取余操作转换为索引
list tuple的底层结构
- list和tuple底层都是顺序表结构
- list底层是可变数组,数组里存放的是元素对象的指针
set的底层结构
哈希表,key就是元素,value都是空
class方法 和 static方法的区别
- class方法的第一个参数是cls,可以访问类属性,类方法
- static方法和普通函数一样,只不过是放在类里,要通过类或实例来调用,但是它不能访问类和实例的属性和方法
装饰器
装饰器是一个接收函数作为参数的闭包函数
它可以在不修改函数内部源代码的情况下,给函数添加额外的功能
元类
-
元类是创建类的类,type还有继承自type的类都是元类
-
作用: 在类定义时(new, init)和 类实例化时(call) 可以添加自定义的功能
-
使用场景: ORM框架中创建一个类就代表数据库中的一个表,但是定义这个类时为了统一需要把里面的类属性全部改为小写,这个时候就要用元类重写new方法,把attrs字典里的key转为小写
魔术方法
__new__
作用
__new__
是一个静态方法,用于创建一个新的实例。它的主要任务是分配内存并返回一个新的对象实例。__new__
方法会被调用以创建一个新的实例,然后将这个实例传递给__init__
方法进行初始化。
__init__
作用
__init__
是构造方法,用于初始化已经创建的实例。它设置对象的初始状态,通常用于初始化实例变量。__init__
方法在__new__
方法之后被调用,用于对新创建的对象进行配置。
__call__
作用
__call__
是一个特殊方法,使得对象能够像函数一样被调用。具体来说,当你在一个对象后面加上括号(例如 obj()),Python 实际上会调用该对象的__call__
方法。
Django的架构模式
它采用了 MVT)架构模式
- Model(模型)
- View(视图)
- Template(模板)