Python面试题集 - 基础语法与核心概念
目录
数据类型与变量
Q1: Python中可变类型和不可变类型有哪些?它们的区别是什么?
详细解答:
不可变类型(Immutable Types):
- int(整数)
- float(浮点数)
- str(字符串)
- tuple(元组)
- frozenset(不可变集合)
- bool(布尔值)
可变类型(Mutable Types):
- list(列表)
- dict(字典)
- set(集合)
- bytearray(字节数组)
核心区别:
-
内存管理方式
- 不可变类型:修改时会创建新对象,原对象保持不变
- 可变类型:修改时在原地修改,不创建新对象
-
代码示例:
python
# 不可变类型示例
a = "hello"
print(id(a)) # 例如:140234567890
a = a + " world"
print(id(a)) # 不同的内存地址,说明创建了新对象
# 可变类型示例
lst = [1, 2, 3]
print(id(lst)) # 例如:140234567900
lst.append(4)
print(id(lst)) # 相同的内存地址,原地修改
- 作为函数参数的影响:
python
def modify_immutable(x):
x = x + 10
return x
def modify_mutable(lst):
lst.append(4)
return lst
num = 5
modify_immutable(num)
print(num) # 输出: 5,原值不变
my_list = [1, 2, 3]
modify_mutable(my_list)
print(my_list) # 输出: [1, 2, 3, 4],原对象被修改
实际应用意义:
- 不可变类型可以作为字典的键
- 不可变类型线程安全
- 理解这个概念有助于避免意外的副作用
Q2: 解释Python中的is和==的区别
详细解答:
核心区别:
==:比较两个对象的值是否相等is:比较两个对象的内存地址(身份)是否相同
代码示例:
python
# 示例1:整数对象
a = 256
b = 256
print(a == b) # True,值相等
print(a is b) # True,小整数对象池(-5到256)
a = 257
b = 257
print(a == b) # True,值相等
print(a is b) # False(在非交互模式下),超出整数对象池范围
# 示例2:列表对象
list1 = [1, 2, 3]
list2 = [1, 2, 3]
list3 = list1
print(list1 == list2) # True,值相等
print(list1 is list2) # False,不同对象
print(list1 is list3) # True,指向同一对象
# 示例3:None的比较
x = None
print(x is None) # 正确方式
print(x == None) # 可以工作但不推荐
Python整数对象池机制:
python
# Python会缓存小整数对象(-5到256)
a = 10
b = 10
print(a is b) # True
# 大整数不会缓存
a = 1000
b = 1000
print(a is b) # False(大多数情况下)
最佳实践:
- 使用
is检查None:if x is None: - 使用
is检查布尔值:if flag is True: - 使用
==比较值:if count == 10: - 使用
is检查对象身份:if obj1 is obj2:
Q3: Python中深拷贝和浅拷贝的区别?
详细解答:
浅拷贝(Shallow Copy):
- 创建新对象,但内部元素仍引用原对象
- 使用方法:
copy.copy()、list.copy()、dict.copy()、切片[:]
深拷贝(Deep Copy):
- 递归复制所有对象,创建完全独立的副本
- 使用方法:
copy.deepcopy()
代码示例:
python
import copy
# 示例1:浅拷贝
original = [[1, 2, 3], [4, 5, 6]]
shallow = copy.copy(original)
# 修改嵌套列表
shallow[0][0] = 999
print(original) # [[999, 2, 3], [4, 5, 6]],原对象受影响
print(shallow) # [[999, 2, 3], [4, 5, 6]]
# 示例2:深拷贝
original = [[1, 2, 3], [4, 5, 6]]
deep = copy.deepcopy(original)
deep[0][0] = 999
print(original) # [[1, 2, 3], [4, 5, 6]],原对象不受影响
print(deep) # [[999, 2, 3], [4, 5, 6]]
# 示例3:不同拷贝方法对比
original = [1, 2, [3, 4]]
# 方法1:切片
copy1 = original[:]
# 方法2:list()构造函数
copy2 = list(original)
# 方法3:copy模块
copy3 = copy.copy(original)
# 这些都是浅拷贝
copy1[2][0] = 999
print(original) # [1, 2, [999, 4]],都受影响
实际应用场景:
python
# 场景1:配置对象拷贝
default_config = {
'database': {
'host': 'localhost',
'port': 5432
},
'cache': {
'enabled': True
}
}
# 使用深拷贝避免修改默认配置
user_config = copy.deepcopy(default_config)
user_config['database']['host'] = '192.168.1.100'
print(default_config['database']['host']) # 'localhost',未受影响
# 场景2:递归数据结构
class Node:
def __init__(self, value):
self.value = value
self.children = []
root = Node(1)
child = Node(2)
root.children.append(child)
# 深拷贝可以处理递归引用
root_copy = copy.deepcopy(root)
性能考虑:
- 浅拷贝:O(n),n为顶层元素数量
- 深拷贝:O(n*m),需要递归复制所有嵌套对象
- 选择原则:只在必要时使用深拷贝
控制流与循环
Q4: Python中for-else和while-else的用法
详细解答:
语法结构:
else子句在循环正常结束时执行- 如果循环被
break中断,else子句不执行
代码示例:
python
# 示例1:for-else查找素数
def is_prime(n):
if n < 2:
return False
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
print(f"{n}可以被{i}整除")
break
else:
# 循环正常结束,没有被break
print(f"{n}是素数")
return True
return False
is_prime(17) # 17是素数
is_prime(15) # 15可以被3整除
# 示例2:在列表中查找元素
def find_element(lst, target):
for i, value in enumerate(lst):
if value == target:
print(f"找到元素{target},索引为{i}")
break
else:
print(f"未找到元素{target}")
find_element([1, 2, 3, 4, 5], 3) # 找到元素3,索引为2
find_element([1, 2, 3, 4, 5], 10) # 未找到元素10
# 示例3:while-else
attempts = 0
max_attempts = 3
while attempts < max_attempts:
password = input("请输入密码: ")
if password == "secret":
print("登录成功!")
break
attempts += 1
print(f"密码错误,剩余尝试次数: {max_attempts - attempts}")
else:
print("尝试次数过多,账户已锁定")
实际应用场景:
python
# 场景1:数据验证
def validate_data(data_list):
for item in data_list:
if not isinstance(item, int):
print(f"发现无效数据: {item}")
return False
else:
print("所有数据验证通过")
return True
# 场景2:资源查找
def find_available_port(start_port, end_port):
import socket
for port in range(start_port, end_port):
try:
sock = socket.socket()
sock.bind(('localhost', port))
sock.close()
print(f"找到可用端口: {port}")
return port
except OSError:
continue
else:
print("在指定范围内未找到可用端口")
return None
最佳实践:
- 使用
for-else替代标志变量 - 提高代码可读性
- 减少嵌套层次
Q5: 列表推导式、字典推导式、集合推导式的使用
详细解答:
1. 列表推导式(List Comprehension)
python
# 基础语法
squares = [x**2 for x in range(10)]
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 带条件过滤
even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares) # [0, 4, 16, 36, 64]
# 嵌套循环
matrix = [[i*j for j in range(1, 4)] for i in range(1, 4)]
print(matrix) # [[1, 2, 3], [2, 4, 6], [3, 6, 9]]
# 展平嵌套列表
nested = [[1, 2], [3, 4], [5, 6]]
flat = [num for sublist in nested for num in sublist]
print(flat) # [1, 2, 3, 4, 5, 6]
# 条件表达式
result = [x if x > 0 else 0 for x in [-2, -1, 0, 1, 2]]
print(result) # [0, 0, 0, 1, 2]
2. 字典推导式(Dict Comprehension)
python
# 基础语法
squares_dict = {x: x**2 for x in range(5)}
print(squares_dict) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# 从两个列表创建字典
keys = ['a', 'b', 'c']
values = [1, 2, 3]
my_dict = {k: v for k, v in zip(keys, values)}
print(my_dict) # {'a': 1, 'b': 2, 'c': 3}
# 字典键值互换
original = {'a': 1, 'b': 2, 'c': 3}
reversed_dict = {v: k for k, v in original.items()}
print(reversed_dict) # {1: 'a', 2: 'b', 3: 'c'}
# 过滤字典
scores = {'Alice': 85, 'Bob': 72, 'Charlie': 90, 'David': 65}
passed = {name: score for name, score in scores.items() if score >= 70}
print(passed) # {'Alice': 85, 'Bob': 72, 'Charlie': 90}
3. 集合推导式(Set Comprehension)
python
# 基础语法
unique_squares = {x**2 for x in [-2, -1, 0, 1, 2]}
print(unique_squares) # {0, 1, 4}
# 去重
numbers = [1, 2, 2, 3, 3, 3, 4]
unique = {x for x in numbers}
print(unique) # {1, 2, 3, 4}
# 过滤条件
vowels = {char.lower() for char in "Hello World" if char.lower() in 'aeiou'}
print(vowels) # {'e', 'o'}
4. 生成器表达式(Generator Expression)
python
# 与列表推导式类似,但使用()而非[]
gen = (x**2 for x in range(10))
print(type(gen)) # <class 'generator'>
print(list(gen)) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 内存效率优势
import sys
list_comp = [x**2 for x in range(1000000)]
gen_exp = (x**2 for x in range(1000000))
print(sys.getsizeof(list_comp)) # ~8MB
print(sys.getsizeof(gen_exp)) # ~112字节
性能对比与最佳实践:
python
import timeit
# 性能测试
def traditional_loop():
result = []
for x in range(1000):
if x % 2 == 0:
result.append(x**2)
return result
def list_comp():
return [x**2 for x in range(1000) if x % 2 == 0]
# 列表推导式通常快20-30%
print(timeit.timeit(traditional_loop, number=10000))
print(timeit.timeit(list_comp, number=10000))
# 最佳实践
# 1. 简单转换用推导式
simple = [x.upper() for x in ['a', 'b', 'c']]
# 2. 复杂逻辑用传统循环
# 不推荐:过于复杂
complex_bad = [process(x) if condition(x) else alternative(x)
for x in data if validate(x) and check(x)]
# 推荐:可读性更好
complex_good = []
for x in data:
if validate(x) and check(x):
if condition(x):
complex_good.append(process(x))
else:
complex_good.append(alternative(x))
函数与作用域
Q6: 解释Python中的LEGB作用域规则
详细解答:
LEGB作用域查找顺序:
- L (Local):局部作用域,函数内部
- E (Enclosing):嵌套函数的外层函数作用域
- G (Global):全局作用域,模块级别
- B (Built-in):内置作用域,Python内置函数
代码示例:
python
# 全局变量
x = "global"
def outer():
# 外层函数变量
x = "enclosing"
def inner():
# 局部变量
x = "local"
print("Inner:", x) # 输出: Inner: local
inner()
print("Outer:", x) # 输出: Outer: enclosing
outer()
print("Global:", x) # 输出: Global: global
# 示例2:变量查找顺序
x = 10 # Global
def demo():
# x = 20 # 如果取消注释,将使用这个local值
def inner():
# x = 30 # 如果取消注释,将使用这个local值
print(x) # 按LEGB顺序查找
inner()
demo() # 输出: 10(使用global值)
global和nonlocal关键字:
python
# global关键字
count = 0
def increment():
global count # 声明使用全局变量
count += 1
return count
print(increment()) # 1
print(increment()) # 2
print(count) # 2
# nonlocal关键字
def outer():
x = 10
def inner():
nonlocal x # 声明使用外层函数的变量
x += 1
return x
print(inner()) # 11
print(x) # 11,外层函数的x被修改
outer()
# 对比:不使用nonlocal
def outer_compare():
x = 10
def inner():
x = 20 # 创建新的局部变量,不影响外层
return x
print(inner()) # 20
print(x) # 10,外层函数的x未被修改
outer_compare()
闭包与作用域:
python
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
# 创建两个独立的计数器
counter1 = make_counter()
counter2 = make_counter()
print(counter1()) # 1
print(counter1()) # 2
print(counter2()) # 1,独立的计数
print(counter1()) # 3
常见陷阱:
python
# 陷阱1:循环中的闭包
functions = []
for i in range(3):
functions.append(lambda: i) # 错误:所有lambda都引用同一个i
for f in functions:
print(f()) # 输出: 2 2 2(都是最后的i值)
# 解决方案1:使用默认参数
functions = []
for i in range(3):
functions.append(lambda x=i: x) # 正确:捕获当前i值
for f in functions:
print(f()) # 输出: 0 1 2
# 解决方案2:使用列表推导式
functions = [lambda x=i: x for i in range(3)]
for f in functions:
print(f()) # 输出: 0 1 2
# 陷阱2:变量未声明就修改
x = 10
def modify():
print(x) # UnboundLocalError
x = 20 # Python看到赋值,认为x是局部变量
# 正确做法
def modify_correct():
global x
print(x) # 10
x = 20
最佳实践:
python
# 1. 最小化全局变量使用
# 不推荐
result = 0
def calculate(x, y):
global result
result = x + y
# 推荐
def calculate(x, y):
return x + y
result = calculate(10, 20)
# 2. 使用类封装状态
class Counter:
def __init__(self):
self.count = 0
def increment(self):
self.count += 1
return self.count
# 3. 函数应该是独立的
def process_data(data):
# 不依赖外部变量
result = do_something(data)
return result
面向对象基础
Q7: Python中的类变量和实例变量的区别
详细解答:
核心区别:
- 类变量:属于类本身,所有实例共享
- 实例变量:属于特定实例,每个实例独立
代码示例:
python
class Dog:
# 类变量
species = "Canis familiaris"
count = 0
def __init__(self, name, age):
# 实例变量
self.name = name
self.age = age
Dog.count += 1 # 修改类变量
# 创建实例
dog1 = Dog("Buddy", 3)
dog2 = Dog("Lucy", 5)
# 访问类变量
print(Dog.species) # Canis familiaris
print(dog1.species) # Canis familiaris(通过实例访问)
print(dog2.species) # Canis familiaris
print(Dog.count) # 2
# 访问实例变量
print(dog1.name) # Buddy
print(dog2.name) # Lucy
# 修改类变量
Dog.species = "Dog"
print(dog1.species) # Dog(所有实例都受影响)
print(dog2.species) # Dog
# 通过实例"修改"类变量(实际创建了实例变量)
dog1.species = "Special Dog"
print(dog1.species) # Special Dog(实例变量)
print(dog2.species) # Dog(仍是类变量)
print(Dog.species) # Dog(类变量未变)
可变类变量的陷阱:
python
class MyClass:
# 陷阱:可变类变量
shared_list = []
def __init__(self, value):
self.shared_list.append(value) # 错误:修改类变量
obj1 = MyClass(1)
obj2 = MyClass(2)
print(obj1.shared_list) # [1, 2],意外共享
print(obj2.shared_list) # [1, 2]
print(MyClass.shared_list) # [1, 2]
# 正确做法
class MyClassCorrect:
def __init__(self, value):
self.my_list = [] # 实例变量
self.my_list.append(value)
obj1 = MyClassCorrect(1)
obj2 = MyClassCorrect(2)
print(obj1.my_list) # [1]
print(obj2.my_list) # [2]
实际应用场景:
python
# 场景1:计数器
class Request:
total_requests = 0 # 类变量:跟踪总请求数
def __init__(self, url):
self.url = url # 实例变量
self.timestamp = datetime.now()
Request.total_requests += 1
@classmethod
def get_total(cls):
return cls.total_requests
# 场景2:配置常量
class DatabaseConfig:
MAX_CONNECTIONS = 100 # 类变量:配置常量
TIMEOUT = 30
def __init__(self, host, port):
self.host = host # 实例变量
self.port = port
self.connection = None
# 场景3:默认值
class Product:
currency = "USD" # 类变量:默认货币
def __init__(self, name, price):
self.name = name
self.price = price
def get_price(self):
return f"{self.currency} {self.price}"
查看变量位置:
python
class Example:
class_var = "I'm a class variable"
def __init__(self):
self.instance_var = "I'm an instance variable"
obj = Example()
# 查看类的属性
print(Example.__dict__)
# {'__module__': '__main__', 'class_var': "I'm a class variable", ...}
# 查看实例的属性
print(obj.__dict__)
# {'instance_var': "I'm an instance variable"}
# 属性查找顺序
print(obj.class_var) # 先找实例,再找类
print(obj.instance_var) # 只在实例中
Q8: 解释Python中的@property装饰器
详细解答:
@property的作用:
- 将方法转换为属性访问
- 实现getter、setter、deleter
- 提供数据封装和验证
基础用法:
python
class Temperature:
def __init__(self, celsius):
self._celsius = celsius
@property
def celsius(self):
"""获取摄氏温度"""
return self._celsius
@celsius.setter
def celsius(self, value):
"""设置摄氏温度,带验证"""
if value < -273.15:
raise ValueError("温度不能低于绝对零度")
self._celsius = value
@celsius.deleter
def celsius(self):
"""删除温度值"""
del self._celsius
@property
def fahrenheit(self):
"""计算华氏温度"""
return self._celsius * 9/5 + 32
@fahrenheit.setter
def fahrenheit(self, value):
"""通过华氏温度设置摄氏温度"""
self._celsius = (value - 32) * 5/9
# 使用示例
temp = Temperature(25)
print(temp.celsius) # 25,像访问属性一样
print(temp.fahrenheit) # 77.0
temp.celsius = 30 # 使用setter
print(temp.celsius) # 30
print(temp.fahrenheit) # 86.0
temp.fahrenheit = 32 # 通过华氏温度设置
print(temp.celsius) # 0.0
# 删除属性
del temp.celsius
实际应用场景:
python
# 场景1:数据验证
class Person:
def __init__(self, name, age):
self._name = name
self._age = age
@property
def age(self):
return self._age
@age.setter
def age(self, value):
if not isinstance(value, int):
raise TypeError("年龄必须是整数")
if value < 0 or value > 150:
raise ValueError("年龄必须在0-150之间")
self._age = value
@property
def name(self):
return self._name
@name.setter
def name(self, value):
if not value or not value.strip():
raise ValueError("名字不能为空")
self._name = value.strip()
person = Person("Alice", 25)
person.age = 30 # 正常设置
# person.age = -5 # ValueError: 年龄必须在0-150之间
# person.age = "thirty" # TypeError: 年龄必须是整数
# 场景2:懒加载
class DataProcessor:
def __init__(self, filename):
self.filename = filename
self._data = None
@property
def data(self):
"""懒加载:只在第一次访问时加载数据"""
if self._data is None:
print("加载数据...")
with open(self.filename, 'r') as f:
self._data = f.read()
return self._data
# 场景3:计算属性
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
@property
def area(self):
"""计算面积"""
return self.width * self.height
@property
def perimeter(self):
"""计算周长"""
return 2 * (self.width + self.height)
rect = Rectangle(5, 10)
print(rect.area) # 50,自动计算
print(rect.perimeter) # 30
# 场景4:向后兼容
class OldAPI:
"""重构时保持API兼容性"""
def __init__(self):
self._new_name = "value"
@property
def old_name(self):
"""旧属性名,向后兼容"""
import warnings
warnings.warn("old_name已弃用,请使用new_name", DeprecationWarning)
return self._new_name
@old_name.setter
def old_name(self, value):
self._new_name = value
对比传统getter/setter:
python
# 传统Java风格(不推荐)
class BadExample:
def __init__(self, value):
self._value = value
def get_value(self):
return self._value
def set_value(self, value):
self._value = value
bad = BadExample(10)
print(bad.get_value()) # 繁琐
bad.set_value(20)
# Python风格(推荐)
class GoodExample:
def __init__(self, value):
self._value = value
@property
def value(self):
return self._value
@value.setter
def value(self, val):
self._value = val
good = GoodExample(10)
print(good.value) # 简洁
good.value = 20
只读属性:
python
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@property
def area(self):
"""只读属性:没有setter"""
import math
return math.pi * self._radius ** 2
@property
def diameter(self):
"""只读属性"""
return self._radius * 2
circle = Circle(5)
print(circle.area) # 78.53981633974483
# circle.area = 100 # AttributeError: can't set attribute
性能考虑:
python
class PerformanceTest:
def __init__(self):
self._cache = None
@property
def expensive_calculation(self):
"""缓存计算结果"""
if self._cache is None:
print("执行复杂计算...")
self._cache = sum(range(1000000))
return self._cache
test = PerformanceTest()
print(test.expensive_calculation) # 第一次:执行计算
print(test.expensive_calculation) # 第二次:使用缓存
异常处理
Q9: Python异常处理的最佳实践
详细解答:
基础语法:
python
# 基本try-except结构
try:
result = 10 / 0
except ZeroDivisionError:
print("不能除以零")
# 捕获多个异常
try:
# 可能引发多种异常的代码
value = int(input("输入数字: "))
result = 10 / value
except ValueError:
print("输入不是有效数字")
except ZeroDivisionError:
print("不能除以零")
# 捕获多个异常(简化版)
try:
value = int(input("输入数字: "))
result = 10 / value
except (ValueError, ZeroDivisionError) as e:
print(f"发生错误: {e}")
# 完整结构:try-except-else-finally
try:
file = open('data.txt', 'r')
data = file.read()
except FileNotFoundError:
print("文件不存在")
except IOError as e:
print(f"IO错误: {e}")
else:
# 没有异常时执行
print("文件读取成功")
process(data)
finally:
# 无论是否异常都执行
if 'file' in locals():
file.close()
print("文件已关闭")
自定义异常:
python
# 自定义异常类
class ValidationError(Exception):
"""数据验证异常"""
pass
class DatabaseError(Exception):
"""数据库操作异常"""
def __init__(self, message, error_code):
super().__init__(message)
self.error_code = error_code
# 使用自定义异常
def validate_age(age):
if not isinstance(age, int):
raise ValidationError("年龄必须是整数")
if age < 0 or age > 150:
raise ValidationError(f"无效年龄: {age}")
return True
try:
validate_age(-5)
except ValidationError as e:
print(f"验证失败: {e}")
# 异常链
class ProcessingError(Exception):
pass
def process_data(data):
try:
result = complex_operation(data)
except ValueError as e:
raise ProcessingError("数据处理失败") from e
try:
process_data(invalid_data)
except ProcessingError as e:
print(f"错误: {e}")
print(f"原因: {e.__cause__}")
最佳实践:
python
# 1. 具体异常优先
# 不推荐:过于宽泛
try:
process()
except Exception:
pass
# 推荐:具体异常
try:
process()
except FileNotFoundError:
handle_missing_file()
except PermissionError:
handle_permission()
except ValueError:
handle_invalid_value()
# 2. 不要使用裸except
# 错误:捕获所有异常包括系统退出
try:
process()
except:
pass
# 正确:指定异常类型
try:
process()
except Exception as e:
log_error(e)
# 3. 资源管理使用上下文管理器
# 不推荐
file = open('data.txt')
try:
data = file.read()
finally:
file.close()
# 推荐
with open('data.txt') as file:
data = file.read()
# 4. 不要隐藏异常
# 错误:吞掉异常
try:
critical_operation()
except Exception:
pass
# 正确:记录或重新抛出
try:
critical_operation()
except Exception as e:
logger.error(f"操作失败: {e}")
raise
# 5. 异常应该是异常情况
# 不推荐:用异常控制流程
def get_value(dictionary, key):
try:
return dictionary[key]
except KeyError:
return None
# 推荐:使用正常逻辑
def get_value(dictionary, key):
return dictionary.get(key)
异常处理模式:
python
# 模式1:EAFP (Easier to Ask for Forgiveness than Permission)
# Python风格:先尝试,失败再处理
def get_value_eafp(dictionary, key):
try:
return dictionary[key]
except KeyError:
return default_value
# 模式2:LBYL (Look Before You Leap)
# 其他语言风格:先检查,再操作
def get_value_lbyl(dictionary, key):
if key in dictionary:
return dictionary[key]
return default_value
# Python更推荐EAFP,因为:
# 1. 避免竞态条件
# 2. 代码更清晰
# 3. 性能更好(成功路径)
# 实际应用:文件操作
# EAFP风格
try:
with open('config.json') as f:
config = json.load(f)
except FileNotFoundError:
config = default_config()
# LBYL风格(不推荐)
import os
if os.path.exists('config.json'):
with open('config.json') as f:
config = json.load(f)
else:
config = default_config()
异常重抛与转换:
python
def convert_temperature(value, unit):
try:
temp = float(value)
if unit == 'C':
return temp * 9/5 + 32
elif unit == 'F':
return (temp - 32) * 5/9
else:
raise ValueError(f"未知单位: {unit}")
except ValueError as e:
# 转换为更具体的异常
raise TemperatureError(f"温度转换失败: {value}") from e
except Exception as e:
# 记录并重抛
logger.exception("意外错误")
raise
# 上下文管理器中的异常
class DatabaseConnection:
def __enter__(self):
self.conn = connect_to_db()
return self.conn
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is not None:
# 发生了异常
self.conn.rollback()
logger.error(f"事务回滚: {exc_val}")
else:
# 正常结束
self.conn.commit()
self.conn.close()
return False # 不抑制异常
# 使用
try:
with DatabaseConnection() as conn:
perform_operations(conn)
except DatabaseError as e:
handle_db_error(e)
总结:
本文档涵盖了Python基础语法与核心概念的关键面试题,包括:
- 数据类型的深入理解(可变/不可变、is/==、深浅拷贝)
- 控制流的高级用法(for-else、推导式)
- 作用域规则(LEGB)
- 面向对象基础(类变量/实例变量、@property)
- 异常处理最佳实践
这些概念是Python编程的基石,掌握它们对于通过技术面试和编写高质量Python代码至关重要。