Python面试题集 - 基础语法与核心概念

Python面试题集 - 基础语法与核心概念

目录


数据类型与变量

Q1: Python中可变类型和不可变类型有哪些?它们的区别是什么?

详细解答:

不可变类型(Immutable Types):

  • int(整数)
  • float(浮点数)
  • str(字符串)
  • tuple(元组)
  • frozenset(不可变集合)
  • bool(布尔值)

可变类型(Mutable Types):

  • list(列表)
  • dict(字典)
  • set(集合)
  • bytearray(字节数组)

核心区别:

  1. 内存管理方式

    • 不可变类型:修改时会创建新对象,原对象保持不变
    • 可变类型:修改时在原地修改,不创建新对象
  2. 代码示例:

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))  # 相同的内存地址,原地修改
  1. 作为函数参数的影响:
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检查Noneif 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作用域查找顺序:

  1. L (Local):局部作用域,函数内部
  2. E (Enclosing):嵌套函数的外层函数作用域
  3. G (Global):全局作用域,模块级别
  4. 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基础语法与核心概念的关键面试题,包括:

  1. 数据类型的深入理解(可变/不可变、is/==、深浅拷贝)
  2. 控制流的高级用法(for-else、推导式)
  3. 作用域规则(LEGB)
  4. 面向对象基础(类变量/实例变量、@property)
  5. 异常处理最佳实践

这些概念是Python编程的基石,掌握它们对于通过技术面试和编写高质量Python代码至关重要。

相关推荐
05候补工程师1 小时前
ROS 2 入门:从零实现小海龟 (Turtlesim) 的手动控制与自动化绘圆
运维·经验分享·python·ubuntu·机器人·自动化
ch.ju1 小时前
Java程序设计(第3版)第三章——数组的遍历
java·开发语言
凯瑟琳.奥古斯特1 小时前
Django Flask FastAPI 三者对比
开发语言·python·django·flask·fastapi
godspeed_lucip1 小时前
LLM和Agent——专题2: LLM as Judge 入门(2)
人工智能·python
青春易逝丶1 小时前
JAVA基础面试题
java·开发语言
百事牛科技1 小时前
Excel安全入门:如何设置和取消打开密码
windows·安全·excel
Austindatabases1 小时前
数据不准确,数据丢失,SQLite怎么保证计算不丢数--SQLite 五脏俱全系列 (5)
java·开发语言·数据库·sqlite
滑稽之神眷顾者1 小时前
基于正倒排索引的文档搜索引擎测试报告
java·开发语言·功能测试
jiayong231 小时前
Python面试题集 - 数据结构与算法
开发语言·python