Python面试30分钟突击掌握

转算法-Python30分钟突击

目录

  1. [Python 数据结构基础](#Python 数据结构基础)
  2. [Python 核心概念](#Python 核心概念)
  3. 常见面试问题
  4. 代码实践题

Python 数据结构基础

1. 数据结构初始化

空对象创建方式
python 复制代码
# 列表(List)- 有序、可变
empty_list = []           # 推荐方式
empty_list = list()       # 构造函数方式

# 字典(Dictionary)- 键值对、可变
empty_dict = {}           # 推荐方式
empty_dict = dict()       # 构造函数方式

# 元组(Tuple)- 有序、不可变
empty_tuple = ()          # 推荐方式
empty_tuple = tuple()     # 构造函数方式

# 集合(Set)- 无序、不重复、可变
empty_set = set()         # 只能用构造函数({} 是空字典)
# empty_set = {}          # ❌ 错误!这是空字典

# 字符串(String)- 不可变
empty_string = ""         # 推荐方式
empty_string = ''         # 单引号也可以
empty_string = str()      # 构造函数方式
为什么空集合不能用 {}

历史原因:

  • Python 2.3 之前只有字典,{} 表示空字典
  • Python 2.4 引入集合,为了向后兼容,{} 仍表示空字典
  • {} 无法区分是字典还是集合,所以空集合必须用 set()

非空时的区别:

python 复制代码
# 字典:有键值对(冒号)
person = {'name': '张三', 'age': 25}  # 明显是字典

# 集合:只有值(没有冒号)
numbers = {1, 2, 3, 4, 5}  # 明显是集合
fruits = {'apple', 'banana'}  # 明显是集合

2. 数据结构特性对比

类型 有序 可变 重复 索引 主要用途
List 有序数据集合
Tuple 不可变有序数据
Dict ✅ (3.7+) ❌ (键) ✅ (键) 键值对映射
Set 去重、成员测试
String 文本数据

3. 数据结构详细说明

列表(List)
python 复制代码
# 创建
my_list = [1, 2, 3]
my_list = list([1, 2, 3])

# 特性
my_list.append(4)        # 添加元素
my_list.insert(0, 0)     # 在指定位置插入
my_list.remove(2)        # 删除元素
my_list.pop()            # 删除并返回最后一个元素
my_list[0]               # 访问元素
my_list[1:3]             # 切片

# 列表推导式
squares = [x**2 for x in range(10)]
evens = [x for x in range(10) if x % 2 == 0]
元组(Tuple)
python 复制代码
# 创建
my_tuple = (1, 2, 3)   
my_tuple = tuple([1, 2, 3])
single_tuple = (5,)      # 单元素元组(注意逗号!)
not_tuple = (5)          # ❌ 这不是元组,是数字 5

# 特性
my_tuple[0]              # 访问元素
my_tuple[1:3]            # 切片
# my_tuple[0] = 10       # ❌ 错误!元组不可变

# 作为字典的键
locations = {
    (0, 0): '原点',
    (10, 20): 'A点'
}

# 解包
x, y, z = my_tuple
字典(Dictionary)
python 复制代码
# 创建
my_dict = {'name': '张三', 'age': 25}
my_dict = dict(name='张三', age=25)

# 访问
my_dict['name']          # 直接访问(键不存在会报错)
my_dict.get('name')      # 安全访问(键不存在返回 None)
my_dict.get('name', '默认值')  # 带默认值

# 操作
my_dict['city'] = '北京'  # 添加/更新
del my_dict['age']       # 删除
'name' in my_dict        # 检查键是否存在

# 字典推导式
squares = {x: x**2 for x in range(5)}
集合(Set)
python 复制代码
# 创建
my_set = {1, 2, 3}
my_set = set([1, 2, 3])

# 特性
my_set.add(4)           # 添加元素
my_set.remove(2)         # 删除元素(不存在会报错)
my_set.discard(2)        # 删除元素(不存在不报错)
3 in my_set              # 成员测试(O(1) 时间复杂度)

# 集合运算
set1 = {1, 2, 3}
set2 = {3, 4, 5}
set1 | set2              # 并集: {1, 2, 3, 4, 5}
set1 & set2              # 交集: {3}
set1 - set2              # 差集: {1, 2}
set1 ^ set2              # 对称差集: {1, 2, 4, 5}

# 集合推导式
evens = {x for x in range(10) if x % 2 == 0}
字符串(String)
python 复制代码
# 创建
my_string = "Hello"
my_string = 'World'
my_string = """多行
字符串"""

# 特性
my_string[0]             # 访问字符
my_string[1:4]           # 切片
my_string.upper()        # 转大写
my_string.lower()        # 转小写
my_string.split(' ')     # 分割
' '.join(['Hello', 'World'])  # 连接

# 格式化
name = "张三"
age = 25
f"姓名: {name}, 年龄: {age}"  # f-string (Python 3.6+)
"姓名: {}, 年龄: {}".format(name, age)  # format
"姓名: %s, 年龄: %d" % (name, age)  # % 格式化

Python 核心概念

1. 可变对象 vs 不可变对象

不可变对象(Immutable)
  • 数字(int, float, complex)
  • 字符串(str)
  • 元组(tuple)
  • 布尔值(bool)
  • frozenset
python 复制代码
# 不可变对象
x = 10
y = x
x = 20
print(y)  # 10(y 不受影响)

# 字符串不可变
s = "Hello"
s[0] = 'h'  # ❌ 错误!TypeError
可变对象(Mutable)
  • 列表(list)
  • 字典(dict)
  • 集合(set)
  • 自定义对象
python 复制代码
# 可变对象
list1 = [1, 2, 3]
list2 = list1
list1.append(4)
print(list2)  # [1, 2, 3, 4](list2 也被修改了!)

# 字典可变
dict1 = {'a': 1}
dict2 = dict1
dict1['b'] = 2
print(dict2)  # {'a': 1, 'b': 2}

2. 参数传递:值传递 vs 引用传递

Python 中一切都是对象引用传递!

python 复制代码
def modify_list(lst):
    lst.append(4)  # 修改原列表

my_list = [1, 2, 3]
modify_list(my_list)
print(my_list)  # [1, 2, 3, 4] - 原列表被修改

def modify_int(x):
    x = 10  # 创建新对象

my_int = 5
modify_int(my_int)
print(my_int)  # 5 - 原值不变(因为整数不可变)

3. 深拷贝 vs 浅拷贝

python 复制代码
import copy

# 浅拷贝
list1 = [[1, 2], [3, 4]]
list2 = copy.copy(list1)  # 或 list1.copy()
list2[0].append(5)
print(list1)  # [[1, 2, 5], [3, 4]] - 内部列表被修改!

# 深拷贝
list1 = [[1, 2], [3, 4]]
list2 = copy.deepcopy(list1)
list2[0].append(5)
print(list1)  # [[1, 2], [3, 4]] - 原列表不变

4. 列表推导式 vs 生成器表达式

python 复制代码
# 列表推导式 - 立即创建列表
squares = [x**2 for x in range(10)]  # 占用内存

# 生成器表达式 - 延迟计算
squares_gen = (x**2 for x in range(10))  # 节省内存
print(list(squares_gen))  # 需要时才计算

5. 装饰器(Decorator)

python 复制代码
def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("函数执行前")
        result = func(*args, **kwargs)
        print("函数执行后")
        return result
    return wrapper

@my_decorator
def greet(name):
    print(f"Hello, {name}")

greet("张三")
# 输出:
# 函数执行前
# Hello, 张三
# 函数执行后

6. 上下文管理器(Context Manager)

python 复制代码
# with 语句
with open('file.txt', 'r') as f:
    content = f.read()
# 文件自动关闭

# 自定义上下文管理器
class MyContext:
    def __enter__(self):
        print("进入上下文")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("退出上下文")
        return False

with MyContext():
    print("执行代码")

7. 生成器(Generator)

python 复制代码
# 生成器函数
def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

gen = fibonacci()
print(next(gen))  # 0
print(next(gen))  # 1
print(next(gen))  # 1

8. 协程(Coroutine)

核心概念

协程是 Python 语言层面的实现,在单线程内的任务切换;多线程是操作系统层面的实现。

  • 协程:Python 语言层面,单线程内切换,用户态调度
  • 多线程:操作系统层面,多线程间切换,内核态调度
基本语法
python 复制代码
import asyncio

async def fetch_data(url):
    # async def 定义协程函数
    await asyncio.sleep(1)  # await 等待异步操作
    return f"数据来自 {url}"

async def main():
    # 并发执行多个协程
    tasks = [fetch_data(f"url{i}") for i in range(5)]
    results = await asyncio.gather(*tasks)
    return results

# 运行异步主函数
results = asyncio.run(main())
python 复制代码
import asyncio  
import time  
  
  
async def fetch_data(url, delay):  
    print(f'开始获取{url}')  
    await asyncio.sleep(delay)  
    print(f'完成获取{url}')  
    return f"{url} 完成"  
  
  
async def main():  
    print("顺序执行")  
    await fetch_data('test1.com', 1)  
    await fetch_data('test2.com', 1)  
  
    print("并发执行开始")  
    await asyncio.gather(fetch_data('test3.com', 1),  
                         fetch_data('test4.com', 1),  
                         fetch_data('test5.com', 1),  
                         fetch_data('test6.com', 1),  
                         )  
    print("并发执行结束")  
  
  
asyncio.run(main())
python 复制代码
import asyncio  
import time  
  
  
async def gather_data(url, delay):  
    print(f'开始请求{url}')  
    await asyncio.sleep(delay)  
    print(f'结束请求{url}')  
  
  
async def main():  
    await gather_data('1.com', 1)  
    await gather_data('2.com', 1)  
  
    await asyncio.gather(gather_data('3.com', 1),  
                         gather_data('4.com', 1),  
                         gather_data('5.com', 1),  
                         gather_data('6.com', 1))  
  
    task1 = asyncio.create_task(gather_data('7.com', 1))  
    task2 = asyncio.create_task(gather_data('8.com', 1))  
  
    await task1  
    await task2  
  
asyncio.run(main())
协程 vs 多线程
特性 协程 多线程
实现层面 Python 语言层面 操作系统层面
执行环境 单线程内 多线程间
内存占用 很小(几 KB) 较大(1-8 MB)
并发数量 几乎无限制(数万+) 受限(几百到几千)
切换开销 很小(纳秒级) 较大(微秒级)
适用场景 I/O 密集型任务 少量并发 I/O
为什么需要协程?

虽然多线程在 I/O 操作时会释放 GIL,但协程仍有明显优势:

  1. 资源开销更小:协程只需几 KB 内存,线程需要 1-8 MB
  2. 并发能力更强:可以轻松处理数万个并发,线程受系统限制
  3. 性能更好:切换开销纳秒级,线程切换需要微秒级
  4. 编程更简单:单线程模型,无需处理锁和同步
实际应用
python 复制代码
import asyncio
import aiohttp

async def fetch_url(session, url):
    async with session.get(url) as response:
        return await response.status

async def main():
    async with aiohttp.ClientSession() as session:
        urls = ['https://api.example.com'] * 100
        tasks = [fetch_url(session, url) for url in urls]
        results = await asyncio.gather(*tasks)  # 并发执行
    return results

# 适合高并发 I/O 场景(Web 服务器、爬虫、API 客户端)
asyncio.run(main())

9. 异常处理

python 复制代码
try:
    result = 10 / 0
except ZeroDivisionError as e:
    print(f"除零错误: {e}")
except Exception as e:
    print(f"其他错误: {e}")
else:
    print("没有错误")
finally:
    print("总是执行")

常见面试问题

1. Python 基础

Q1: Python 中 is== 的区别?
python 复制代码
# == 比较值
a = [1, 2, 3]
b = [1, 2, 3]
print(a == b)  # True(值相同)

# is 比较对象标识(内存地址)
print(a is b)  # False(不同对象)

# 小整数和字符串会被缓存
x = 256
y = 256
print(x is y)  # True(小整数缓存)

x = 257
y = 257
print(x is y)  # False(大整数不缓存)
Q2: *args**kwargs 是什么?
python 复制代码
def func(*args, **kwargs):
    # *args: 接收任意数量的位置参数(元组)
    # **kwargs: 接收任意数量的关键字参数(字典)
    print(f"args: {args}")
    print(f"kwargs: {kwargs}")

func(1, 2, 3, name='张三', age=25)
# args: (1, 2, 3)
# kwargs: {'name': '张三', 'age': 25}


def print_info(*args, **kwargs):
	for arg in args:
		print(f'{arg}')
		
	for key, value in kwargs.items():
		print(f'{key} {value}')
		
print_info(1,2,3,4, name='name', age='age')


def greet(name, greeting='hello'):
	# 解包出来 name
	# 解包出来 greeting
	print(f'{name} {greeting}')

def wrapper(func, *args, **kwargs):
	# args 被打包成 ('lili',)
	# kwargs 被打包成 {greeting:'hello'}
	func(*args, **kwargs)
	
wrapper(greet, "lili", greeting='hello')
Q3: Python 的 GIL(全局解释器锁)是什么?
  • GIL 是 CPython 解释器的特性
  • 同一时刻只有一个线程执行 Python 字节码
  • 影响 CPU 密集型任务,但不影响 I/O 密集型任务
  • 可以通过多进程(multiprocessing)绕过 GIL
Q4: __init____new__ 的区别?
python 复制代码
class MyClass:
    def __new__(cls, *args, **kwargs):
        # 创建实例(在 __init__ 之前调用)
        print("创建实例")
        return super().__new__(cls)

    def __init__(self, value):
        # 初始化实例
        print("初始化实例")
        self.value = value

2. 数据结构相关

Q5: 如何实现一个单例模式?
python 复制代码
class Singleton:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

# 或使用装饰器
def singleton(cls):
    instances = {}
    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return get_instance
Q6: 如何合并两个字典?
python 复制代码
dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'd': 4}

# Python 3.5+
merged = {**dict1, **dict2}

# Python 3.9+
merged = dict1 | dict2

# 传统方式
merged = dict1.copy()
merged.update(dict2)
Q7: 如何去除列表中的重复元素?
python 复制代码
my_list = [1, 2, 2, 3, 3, 3]

# 方法1: 使用集合(不保持顺序)
unique = list(set(my_list))

# 方法2: 使用字典(保持顺序,Python 3.7+)
unique = list(dict.fromkeys(my_list))

# 方法3: 列表推导式(保持顺序)
seen = set()
unique = [x for x in my_list if x not in seen and not seen.add(x)]

3. 算法和性能

Q8: 列表和集合的查找时间复杂度?
python 复制代码
# 列表查找: O(n) - 线性查找
my_list = [1, 2, 3, 4, 5]
if 3 in my_list:  # 需要遍历
    pass

# 集合查找: O(1) - 哈希表查找
my_set = {1, 2, 3, 4, 5}
if 3 in my_set:  # 直接查找
    pass
Q9: 如何反转一个列表?
python 复制代码
my_list = [1, 2, 3, 4, 5]

# 方法1: 切片
reversed_list = my_list[::-1]

# 方法2: reverse()(原地修改)
my_list.reverse()

# 方法3: reversed()(返回迭代器)
reversed_list = list(reversed(my_list))
Q10: 如何找到列表中的最大值和最小值?
python 复制代码
my_list = [3, 1, 4, 1, 5, 9, 2, 6]

# 内置函数
max_value = max(my_list)
min_value = min(my_list)

# 手动实现
max_value = my_list[0]
for x in my_list:
    if x > max_value:
        max_value = x

4. 面向对象

Q11: 类变量和实例变量的区别?
python 复制代码
class MyClass:
    class_var = "类变量"  # 所有实例共享

    def __init__(self, value):
        self.instance_var = value  # 每个实例独有

obj1 = MyClass(1)
obj2 = MyClass(2)

print(obj1.class_var)  # "类变量"
print(obj2.class_var)  # "类变量"
print(obj1.instance_var)  # 1
print(obj2.instance_var)  # 2
Q12: 私有变量和受保护变量?
python 复制代码
class MyClass:
    def __init__(self):
        self.public = "公开"        # 公开
        self._protected = "受保护"  # 约定(单下划线)
        self.__private = "私有"     # 名称修饰(双下划线)

obj = MyClass()
print(obj.public)      # ✅ 可以访问
print(obj._protected)  # ⚠️ 可以访问(但不推荐)
print(obj.__private)   # ❌ 错误!实际名称是 _MyClass__private
Q13: 多继承的 MRO(方法解析顺序)?
python 复制代码
class A:
    def method(self):
        print("A")

class B(A):
    def method(self):
        print("B")

class C(A):
    def method(self):
        print("C")

class D(B, C):
    pass

d = D()
d.method()  # 输出: B(按 MRO 顺序)
print(D.__mro__)  # 查看方法解析顺序

5. 高级特性

Q14: 什么是闭包?
python 复制代码
def outer_function(x):
    def inner_function(y):
        return x + y
    return inner_function

closure = outer_function(10)
print(closure(5))  # 15(闭包记住了 x=10)
Q15: 如何实现一个迭代器?
python 复制代码
class MyIterator:
    def __init__(self, data):
        self.data = data
        self.index = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.index >= len(self.data):
            raise StopIteration
        value = self.data[self.index]
        self.index += 1
        return value

my_iter = MyIterator([1, 2, 3])
for item in my_iter:
    print(item)
Q16: 描述符(Descriptor)是什么?
python 复制代码
class Descriptor:
    def __init__(self, name):
        self.name = name

    def __get__(self, obj, objtype=None):
        return obj.__dict__.get(self.name)

    def __set__(self, obj, value):
        obj.__dict__[self.name] = value

class MyClass:
    x = Descriptor('x')

obj = MyClass()
obj.x = 10
print(obj.x)  # 10

6. 并发和异步

Q17: 多线程 vs 多进程?
python 复制代码
# 多线程(适合 I/O 密集型)
import threading

def worker():
    print("线程执行")

thread = threading.Thread(target=worker)
thread.start()

# 多进程(适合 CPU 密集型)
import multiprocessing

def worker():
    print("进程执行")

process = multiprocessing.Process(target=worker)
process.start()
Q18: 如何使用 asyncio?
python 复制代码
import asyncio

async def fetch_data():
    await asyncio.sleep(1)
    return "数据"

async def main():
    tasks = [fetch_data() for _ in range(5)]
    results = await asyncio.gather(*tasks)
    return results

results = asyncio.run(main())





import asyncio

async def fetch_data():
    await asyncio.sleep(1)
    return "数据"

async def main():
    tasks = [fetch_data() for _ in range(5)]
    results = await asyncio.gather(*tasks)
    return results

results = asyncio.run(main())

代码实践题

1. 实现一个 LRU 缓存

python 复制代码
from collections import OrderedDict

  

class LRUCache:

    def __init__(self, capacity) -> None:

        if capacity <= 0:

            raise ValueError("capacity must be > 0")

        self.capacity = capacity

        self.cache = OrderedDict()

  

    def get(self, key: int) -> int | None:

        if key in self.cache:

            self.cache.move_to_end(key)

            return self.cache[key]

        return None

  

    def put(self, key : int, value : int) -> None:

        self.cache[key] = value

        self.cache.move_to_end(key)

        if len(self.cache) > self.capacity:

            self.cache.popitem(last=False)

2. 实现一个装饰器来测量函数执行时间

python 复制代码
import time
from functools import wraps

def timing_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__} 执行时间: {end - start:.4f} 秒")
        return result
    return wrapper

@timing_decorator
def slow_function():
    time.sleep(1)
    return "完成"

3. 实现一个单例模式的线程安全版本

python 复制代码
import threading

class Singleton:

    _instance = None

    _lock = threading.Lock()

    def __new__(cls, *args, **kwargs):

        if cls._instance is None:

            with cls._lock:

                if cls._instance is None:

                    cls._instance = super().__new__(cls)

        return cls._instance

  

    def __init__(self, *args, **kwargs):

        if getattr(self, "_singleton_initialized", False):

            return

        self._singleton_initialized = True

        # 仅首次构造执行:把需要初始化的成员写在这里```

### 4. 实现一个简单的上下文管理器

```python
class FileManager:
    def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode
        self.file = None

    def __enter__(self):
        self.file = open(self.filename, self.mode)
        return self.file

    def __exit__(self, exc_type, exc_val, exc_tb):
        if self.file:
            self.file.close()
        return False

# 使用
with FileManager('test.txt', 'w') as f:
    f.write('Hello')

5. 实现一个生成器来生成斐波那契数列

python 复制代码
def fibonacci(n):
    a, b = 0, 1
    count = 0
    while count < n:
        yield a
        a, b = b, a + b
        count += 1

# 使用
for num in fibonacci(10):
    print(num)
    
    
    
################
def fibonacci():
	a, b = 0, 1
	while True:
		yield a
		a, b = b, a+b

fib = fibonacci()
print(next(fib))
print(next(fib))

面试技巧

1. 准备阶段

  • 熟悉 Python 官方文档
  • 练习 LeetCode Python 题目
  • 了解常用库(requests, pandas, numpy 等)
  • 准备项目经验和技术难点

2. 回答问题时

  • 先说思路,再写代码
  • 考虑边界情况
  • 讨论时间复杂度和空间复杂度
  • 提出优化方案

3. 常见陷阱

  • 可变默认参数问题
  • 列表推导式的作用域
  • 闭包变量绑定
  • 深拷贝和浅拷贝

4. 推荐学习资源

  • Python 官方文档
  • 《流畅的 Python》
  • 《Python Cookbook》
  • LeetCode
  • GitHub 上的 Python 项目

总结

这份文档涵盖了 Python 面试的核心知识点:

  • ✅ 数据结构基础(初始化、特性、使用场景)
  • ✅ Python 核心概念(可变/不可变、参数传递、拷贝等)
  • ✅ 常见面试问题(基础、数据结构、算法、面向对象等)
  • ✅ 代码实践题(LRU、装饰器、单例等)

记住:理解原理比死记硬背更重要!

相关推荐
qq_20815408852 小时前
瑞树6代流程分析
javascript·python
好运的阿财2 小时前
大模型热切换功能完整实现指南
人工智能·python·程序人生·开源·ai编程
爱码小白2 小时前
数据库多表命名的通用规范
数据库·python·mysql
大喵桑丶2 小时前
ZABBIX7二次开发AI监控数据调取杂记
大数据·人工智能·python
WangJunXiang62 小时前
Python网络编程
开发语言·网络·python
_下雨天.2 小时前
Python 网络编程
开发语言·网络·python
啦啦啦_99993 小时前
1. 面向对象基础
python
小陈工3 小时前
2026年4月8日技术资讯洞察:边缘AI推理框架竞争白热化,Python后端开发者的机遇与挑战
开发语言·数据库·人工智能·python·微服务·回归
赵药师3 小时前
YOLO中task.py改复杂的模块
python·深度学习·yolo