前言
最近想换个环境,所以一直在投外包的简历,先面面外包,涨点经验
日期2025/1/19
1、自我介绍
2、python哪些数据类型是可变的,哪些是不可变的
不可变数据类型(Immutable)
不可变对象一旦创建,其内容不能被修改。如果尝试修改,实际上是创建了一个新的对象。
- 整数(int)
示例:x = 10,x的值不能直接修改,只能重新赋值。 - 浮点数(float)
示例:y = 3.14,y的值不能直接修改,只能重新赋值。 - 布尔值(bool)
示例:z = True,z的值不能直接修改,只能重新赋值。 - 字符串(str)
示例:s = "hello",字符串的内容不能直接修改(如s[0] = 'H'会报错),只能通过重新赋值或生成新字符串。 - 元组(tuple)
示例:t = (1, 2, 3),元组的内容不能修改(如t[0] = 4会报错),只能重新赋值。 - 冻结集合(frozenset)
示例:fs = frozenset([1, 2, 3]),冻结集合的内容不能修改。
可变数据类型(Mutable)
可变对象创建后,其内容可以被修改,而对象本身(内存地址)不变。
-
列表(list)
示例:lst = [1, 2, 3],可以通过索引修改元素(如lst[0] = 10),也可以添加或删除元素。 -
字典(dict)
示例:d = {'a': 1, 'b': 2},可以修改、添加或删除键值对(如d['a'] = 10或d['c'] = 3)。 -
集合(set)
示例:s = {1, 2, 3},可以添加或删除元素(如s.add(4)或s.remove(1))。 -
字节数组(bytearray)
示例:ba = bytearray(b'hello'),可以通过索引修改字节(如ba[0] = 72)。
3、django和flask的区别
-
Django:
- “全栈”框架:提供了从数据库(ORM)、模板引擎、表单处理到用户认证等一整套工具,开箱即用。
- 约定优于配置:Django 有固定的项目结构和默认配置,适合快速开发标准化项目。
- 适合大型项目:内置功能丰富,适合构建复杂的企业级应用。
-
Flask:
- “微框架” :核心功能简单,只提供最基本的路由和请求处理,其他功能通过扩展实现。
- 灵活性强:开发者可以根据需求自由选择组件和工具,适合定制化开发。
- 适合小型项目或 API 服务:轻量级,适合快速开发小型应用或 RESTful API。
4、django的values和value_list俩个方法有什么区别
1. values()
- 返回类型:返回一个包含字典的 QuerySet,每个字典代表一行数据,字典的键是字段名,值是对应的字段值。
- 用法:适用于需要以字典形式获取多个字段的情况。
2. values_list()
- 返回类型:返回一个包含元组的 QuerySet,每个元组代表一行数据,元组中的元素是对应字段的值。
- 用法:适用于需要以元组形式获取多个字段的情况,或者只获取单个字段时,可以设置
flat=True,返回一个简单的列表。
总结
- 使用
values()时,返回的是字典,适合需要字段名的场景。 - 使用
values_list()时,返回的是元组,适合需要简单数据结构的场景,特别是当只需要一个字段时,可以使用flat=True返回一个列表。
5、django中的Q函数和F函数有什么区别
在 Django 中,Q 和 F 是用于构建查询的两个不同工具,它们各自有不同的用途和功能。
1. Q 对象
-
定义:
Q对象用于构建复杂的查询条件,特别是当需要使用逻辑运算符(如 AND、OR)时。 -
用途:可以用于组合多个查询条件,支持嵌套和逻辑运算。
-
示例:
from django.db.models import Q # 查询名字为 'Alice' 或者年龄大于 30 的用户 users = User.objects.filter(Q(name='Alice') | Q(age__gt=30))
2. F 对象
-
定义:
F对象用于引用模型字段的值,允许在查询中使用字段之间的比较。 -
用途:可以在查询中进行字段之间的运算,比如更新某个字段的值为另一个字段的值。
-
示例:
from django.db.models import F # 将用户的年龄增加 1 User.objects.filter(name='Alice').update(age=F('age') + 1)
总结
- Q:用于构建复杂的查询条件,支持逻辑运算。
- F:用于引用模型字段的值,支持字段之间的运算。
6、jwt、session、cookie的区别,jwt由哪几部分组成
JWT(JSON Web Token)、Session 和 Cookie 是 Web 开发中常用的身份验证和状态管理机制,它们之间有一些重要的区别:
1. JWT(JSON Web Token)
- 定义:JWT 是一种开放标准(RFC 7519),用于在网络应用环境间以 JSON 对象安全地传递信息。信息可以被验证和信任,因为它是数字签名的。
- 存储:通常存储在客户端的本地存储或 Cookie 中。
- 无状态:JWT 是无状态的,服务器不需要存储会话信息。所有信息都包含在 JWT 中。
- 结构:JWT 由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。
- 使用场景:适用于分布式系统和微服务架构,能够在不同的服务间传递用户身份信息。
2. Session
- 定义:Session 是一种在服务器端存储用户会话信息的机制。每个用户在服务器上都有一个唯一的会话 ID。
- 存储:会话数据存储在服务器的内存或数据库中,客户端通过 Cookie 存储会话 ID。
- 有状态:Session 是有状态的,服务器需要维护会话信息。
- 安全性:由于会话数据存储在服务器上,安全性相对较高。
- 使用场景:适用于需要存储大量用户数据的应用,如购物车、用户偏好设置等。
3. Cookie
- 定义:Cookie 是由服务器发送到客户端并存储在用户浏览器中的小数据块。它们用于存储用户的状态信息。
- 存储:存储在客户端的浏览器中,通常用于保存用户的登录状态、偏好设置等。
- 有状态:Cookie 本身不存储会话信息,但可以与 Session 结合使用。
- 大小限制:每个 Cookie 的大小通常限制在 4KB 左右。
- 使用场景:适用于存储小量的用户信息,如用户偏好、登录状态等。
总结
- JWT 是一种无状态的身份验证机制,适合分布式系统。
- Session 是有状态的,适合需要存储大量用户数据的应用。
- Cookie 是存储在客户端的小数据块,通常用于保存用户的状态信息。
7、mysql如何对sql进行调优
1. 使用索引
- 创建索引:在查询中经常使用的列上创建索引,可以显著提高查询速度。
- 选择合适的索引类型:根据查询的特点选择合适的索引类型(如 B-tree、哈希索引等)。
- 避免过多索引:虽然索引可以加速查询,但过多的索引会影响插入、更新和删除操作的性能。
2. 优化查询语句
- 选择必要的列:使用
SELECT语句时,只选择需要的列,避免使用SELECT *。 - 使用 WHERE 子句:通过
WHERE子句过滤不必要的数据,减少返回的行数。 - 避免子查询:尽量使用连接(JOIN)代替子查询,尤其是在子查询返回大量数据时。
3. 使用连接(JOIN)
- 选择合适的连接类型:根据数据的特点选择合适的连接类型(如 INNER JOIN、LEFT JOIN 等)。
- 优化连接条件:确保连接条件使用索引列,以提高连接效率。
4. 分析执行计划
- 使用 EXPLAIN:在执行 SQL 查询之前,使用
EXPLAIN语句查看查询的执行计划,识别潜在的性能瓶颈。 - 分析执行顺序:检查表的访问顺序、使用的索引、连接类型等,确保查询的执行顺序是最优的。
8、mysql中where和having的区别
在 MySQL 中,WHERE 和 HAVING 都用于过滤数据,但它们的使用场景和功能有所不同。以下是它们的主要区别:
1. 使用位置
- WHERE:在
SELECT语句中,WHERE子句用于在数据被分组之前过滤记录。它通常用于过滤行数据。 - HAVING:在
GROUP BY子句之后使用,HAVING用于过滤分组后的结果。它通常用于过滤聚合函数的结果。
2. 适用条件
- WHERE:可以用于任何列的条件,包括非聚合列。
- HAVING:通常用于聚合函数(如
SUM、COUNT、AVG等)的条件。
2025/2/28 更新 软通动力
1、进程、线程和协程的区别
1. 基本概念
-
进程:
- 进程是操作系统分配资源的基本单位,每个进程有独立的内存空间。
- 进程之间相互隔离,一个进程崩溃不会影响其他进程。
- 在 Python 中,可以通过
multiprocessing模块创建和管理进程。
-
线程:
- 线程是操作系统调度的基本单位,是进程内的执行单元。
- 线程共享进程的内存空间,因此线程间通信更方便,但也更容易出现资源竞争问题。
- 在 Python 中,可以通过
threading模块创建和管理线程。
-
协程:
- 协程是一种用户态的轻量级线程,由程序员在代码中显式控制调度。
- 协程不需要操作系统介入,切换开销小,适合高并发 I/O 密集型任务。
- 在 Python 中,可以通过
asyncio模块和async/await语法实现协程。
2. 区别与联系
| 特性 | 进程 | 线程 | 协程 |
|---|---|---|---|
| 资源占用 | 高(独立内存空间) | 中(共享内存空间) | 低(用户态调度) |
| 切换开销 | 高 | 中 | 低 |
| 并发性 | 多进程并行 | 多线程并发 | 高并发(单线程内) |
| 适用场景 | CPU 密集型任务 | I/O 密集型任务 | 高并发 I/O 密集型任务 |
| 通信方式 | 进程间通信(IPC) | 共享内存 | 事件循环、回调 |
| 隔离性 | 高(进程间隔离) | 低(线程间共享内存) | 中(任务间独立) |
3. 实际应用
-
进程:
-
适合 CPU 密集型任务,如科学计算、图像处理。
-
示例:
from multiprocessing import Process def task(): print("Process is running") if __name__ == "__main__": p = Process(target=task) p.start() p.join()
-
-
线程:
-
适合 I/O 密集型任务,如文件读写、网络请求。
-
示例:
from threading import Thread def task(): print("Thread is running") t = Thread(target=task) t.start() t.join()
-
-
协程:
-
适合高并发 I/O 密集型任务,如 Web 服务器、爬虫。
-
示例:
import asyncio async def task(): print("Coroutine is running") async def main(): await asyncio.gather(task(), task()) asyncio.run(main())
-
2、python列表和字典的一些方法
列表(List)常用方法
-
append():-
功能: 在列表末尾添加一个元素。
-
例子:
my_list = [1, 2, 3] my_list.append(4) print(my_list) # 输出: [1, 2, 3, 4]
-
-
extend():-
功能: 将一个列表的所有元素添加到另一个列表的末尾。
-
例子:
my_list = [1, 2, 3] my_list.extend([4, 5]) print(my_list) # 输出: [1, 2, 3, 4, 5]
-
-
insert():-
功能: 在指定位置插入一个元素。
-
例子:
my_list = [1, 2, 3] my_list.insert(1, 1.5) print(my_list) # 输出: [1, 1.5, 2, 3]
-
-
remove():-
功能: 移除列表中第一个匹配的元素。
-
例子:
my_list = [1, 2, 3, 2] my_list.remove(2) print(my_list) # 输出: [1, 3, 2]
-
-
pop():-
功能: 移除并返回列表中指定位置的元素(默认是最后一个元素)。
-
例子:
my_list = [1, 2, 3] popped_element = my_list.pop(1) print(popped_element) # 输出: 2 print(my_list) # 输出: [1, 3]
-
-
index():-
功能: 返回列表中第一个匹配元素的索引。
-
例子:
my_list = [1, 2, 3, 2] index = my_list.index(2) print(index) # 输出: 1
-
-
count():-
功能: 返回列表中某个元素出现的次数。
-
例子:
my_list = [1, 2, 3, 2] count = my_list.count(2) print(count) # 输出: 2
-
-
sort():-
功能: 对列表进行排序(默认是升序)。
-
例子:
my_list = [3, 1, 2] my_list.sort() print(my_list) # 输出: [1, 2, 3]
-
-
reverse():-
功能: 反转列表中的元素顺序。
-
例子:
my_list = [1, 2, 3] my_list.reverse() print(my_list) # 输出: [3, 2, 1]
-
字典(Dictionary)常用方法
-
keys():-
功能: 返回字典中所有的键。
-
例子:
my_dict = {'a': 1, 'b': 2, 'c': 3} keys = my_dict.keys() print(keys) # 输出: dict_keys(['a', 'b', 'c'])
-
-
values():-
功能: 返回字典中所有的值。
-
例子:
my_dict = {'a': 1, 'b': 2, 'c': 3} values = my_dict.values() print(values) # 输出: dict_values([1, 2, 3])
-
-
items():-
功能: 返回字典中所有的键值对。
-
例子:
my_dict = {'a': 1, 'b': 2, 'c': 3} items = my_dict.items() print(items) # 输出: dict_items([('a', 1), ('b', 2), ('c', 3)])
-
-
get():-
功能: 返回指定键的值,如果键不存在则返回默认值(默认为
None)。 -
例子:
my_dict = {'a': 1, 'b': 2, 'c': 3} value = my_dict.get('b') print(value) # 输出: 2
-
-
pop():-
功能: 移除并返回指定键的值。
-
例子:
my_dict = {'a': 1, 'b': 2, 'c': 3} popped_value = my_dict.pop('b') print(popped_value) # 输出: 2 print(my_dict) # 输出: {'a': 1, 'c': 3}
-
-
update():-
功能: 更新字典中的键值对(可以添加新的键值对或更新已有的键值对)。
-
例子:
my_dict = {'a': 1, 'b': 2} my_dict.update({'b': 3, 'c': 4}) print(my_dict) # 输出: {'a': 1, 'b': 3, 'c': 4}
-
-
clear():-
功能: 清空字典中的所有键值对。
-
例子:
my_dict = {'a': 1, 'b': 2} my_dict.clear() print(my_dict) # 输出: {}
-
3、python的生成器和迭代器
在Python中,生成器(Generator) 和迭代器(Iterator) 是用于处理可迭代对象的重要概念。它们可以帮助你高效地处理大量数据,尤其是在内存有限的情况下。
1. 迭代器(Iterator)
-
定义:迭代器是一个实现了迭代协议的对象,即它必须包含
__iter__()和__next__()方法。 -
作用:迭代器用于逐个访问集合中的元素,而不需要一次性将所有元素加载到内存中。
-
特点:
- 迭代器只能向前遍历,不能回退。
- 一旦迭代器耗尽(即
__next__()引发StopIteration异常),就不能再次使用。
示例:
class MyIterator:
def __init__(self, max_num):
self.max_num = max_num
self.current = 0
def __iter__(self):
return self
def __next__(self):
if self.current < self.max_num:
self.current += 1
return self.current
else:
raise StopIteration
# 使用迭代器
my_iter = MyIterator(5)
for num in my_iter:
print(num)
2. 生成器(Generator)
-
定义:生成器是一种特殊的迭代器,使用
yield关键字来生成值。 -
作用:生成器允许你按需生成值,而不是一次性生成所有值,从而节省内存。
-
特点:
- 生成器函数在调用时不会立即执行,而是返回一个生成器对象。
- 每次调用
next()或使用for循环时,生成器函数会执行到yield语句,返回一个值,并暂停执行,直到下一次调用。
示例:
def my_generator(max_num):
current = 0
while current < max_num:
current += 1
yield current
# 使用生成器
gen = my_generator(5)
for num in gen:
print(num)
3. 生成器表达式
生成器表达式与列表推导式类似,但使用圆括号而不是方括号。它返回一个生成器对象,而不是一个列表。
示例:
gen_exp = (x * x for x in range(5))
for num in gen_exp:
print(num)
4. 迭代器与生成器的区别
- 实现方式:迭代器通常通过类实现,而生成器通过函数实现。
- 内存使用:生成器更节省内存,因为它按需生成值,而不是一次性生成所有值。
- 代码简洁性:生成器通常更简洁,尤其是使用
yield时。
5. 使用场景
- 迭代器:适用于需要自定义迭代行为的场景。
- 生成器:适用于处理大量数据或需要按需生成值的场景。
6. 内置函数
Python提供了许多内置函数来处理迭代器和生成器,例如:
iter():将可迭代对象转换为迭代器。next():获取迭代器的下一个值。enumerate():为可迭代对象添加索引。zip():将多个可迭代对象组合在一起。
示例:
# 使用内置函数
my_list = [1, 2, 3]
my_iter = iter(my_list)
print(next(my_iter)) # 输出: 1
4、mysql的InnoDB和MyISAM引擎区别
InnoDB 和 MyISAM 是 MySQL 数据库中两种常见的存储引擎,它们在功能、性能和适用场景上有显著的区别。以下是它们的主要区别:
1. 事务支持
- InnoDB:支持事务(ACID 特性),可以确保数据的完整性和一致性。适用于需要事务处理的应用程序,如银行系统、电商平台等。
- MyISAM:不支持事务,适合不需要事务支持的简单查询和插入操作。
2. 外键支持
- InnoDB:支持外键约束,可以维护表与表之间的引用完整性。
- MyISAM:不支持外键。
3. 锁定机制
- InnoDB:支持行级锁定,可以在更细粒度的层次上进行并发控制,减少锁冲突,提高并发性能。
- MyISAM:仅支持表级锁定,当有写操作时,会锁定整个表,影响并发性能。
4. 崩溃恢复
- InnoDB:具有崩溃恢复能力,可以在数据库崩溃后通过日志文件恢复数据。
- MyISAM:崩溃后数据恢复较为困难,可能会导致数据丢失。
5. 存储结构
- InnoDB:数据和索引存储在一个文件中(表空间),支持更复杂的查询和操作。
- MyISAM:数据和索引分别存储在不同的文件中,结构较为简单。
6. 全文索引
- InnoDB:在 MySQL 5.6 及以上版本中支持全文索引。
- MyISAM:较早支持全文索引,适用于全文搜索场景。
7. 性能
- InnoDB:在需要高并发、事务处理的场景下性能更好。
- MyISAM:在大量读取操作且不需要事务支持的场景下性能较好。
8. 适用场景
- InnoDB:适用于需要事务、外键、高并发和复杂查询的应用场景。
- MyISAM:适用于读多写少、不需要事务支持的简单应用场景。
总结
- InnoDB:更适合现代应用,特别是在需要事务处理和高并发的情况下。
- MyISAM:适用于传统应用,特别是在读取操作远多于写入操作的场景。