【面试宝典】Python 全栈面试实战

实验环境:华为云 ECS 服务器 ecs-5d9b-0001 (119.8.30.110)
操作系统:Ubuntu 24.04.4 LTS (Linux 6.8.0-106-generic)
Python版本:3.12.3
实验时间:2026-07-05
实验方式:所有代码均在 ECS 服务器上真实上机运行


目录

序号 章节 知识点
01 Python 数据类型 数据类型创建与操作、面试题
02 Python 函数和高阶函数 函数定义、高阶函数、装饰器
03 Python 包与模块、异常处理 模块导入、异常处理机制
04 Python 面向对象 OOP三大特性、魔术方法、内存管理
05 Python 并发编程 线程、协程、锁、GIL
06 Python 设计模式 单例、工厂、装饰器、观察者等
07 Python 数据库 SQLite/Redis/MongoDB
08 Python Web 框架 Flask/Django/FastAPI
09 Python 爬虫 HTTP请求、HTML解析、数据存储
10 Python 自动化测试 unittest/Mock/接口测试/Web测试

服务器环境信息

主机名: ecs-5d9b-0001
操作系统: Ubuntu 24.04.4 LTS
内核: Linux 6.8.0-106-generic x86_64
Python: 3.12.3
CPU: 8vCPUs (c6s.2xlarge.2)
内存: 16GiB
弹性公网IP: 119.8.30.110
私有IP: 192.168.0.186


04 Python 面向对象

知识点

1.Python面向对象的理解 2.Python面向对象特性的使用 3.Python内存中对象的管理

简介

面向对象编程(OOP)是Python的核心范式。涵盖封装、继承、多态三大特性,以及魔术方法、描述符、元类、内存管理和垃圾回收等高级主题。

实验源码

#!/usr/bin/env python3
"""
【面试宝典】Python 面向对象
知识点: 1.Python面向对象的理解 2.Python面向对象特性的使用 3.Python内存中对象的管理
"""

print("=" * 70)
print("【面试宝典】Python 面向对象")
print("=" * 70)

# ============================================================
# 1. 类与对象基础
# ============================================================
print("\n" + "=" * 70)
print("1. 类与对象基础")
print("=" * 70)

# 1.1 类的定义
print("\n--- 1.1 类的定义 ---")
class Person:
    # 类变量
    species = "Homo sapiens"
    count = 0

    # 构造方法
    def __init__(self, name, age):
        self.name = name  # 实例变量
        self.age = age
        Person.count += 1

    # 实例方法
    def introduce(self):
        return f"我是 {self.name}, 今年 {self.age} 岁"

    # 类方法
    @classmethod
    def get_count(cls):
        return f"已创建 {cls.count} 个 Person 对象"

    # 静态方法
    @staticmethod
    def is_adult(age):
        return age >= 18

    # __repr__
    def __repr__(self):
        return f"Person(name='{self.name}', age={self.age})"

    # __str__
    def __str__(self):
        return f"{self.name} ({self.age}岁)"

p1 = Person("Alice", 30)
p2 = Person("Bob", 25)
print(f"p1 = {p1}")
print(f"repr(p1) = {repr(p1)}")
print(f"p1.introduce() = {p1.introduce()}")
print(f"Person.get_count() = {Person.get_count()}")
print(f"Person.is_adult(20) = {Person.is_adult(20)}")
print(f"Person.species = {Person.species}")

# 1.2 实例变量 vs 类变量
print("\n--- 1.2 实例变量 vs 类变量 ---")
print(f"p1.name = {p1.name} (实例变量)")
print(f"p1.species = {p1.species} (类变量)")
print(f"p2.species = {p2.species} (类变量)")

# 修改类变量影响所有实例
Person.species = "Human"
print(f"\n修改 Person.species = 'Human' 后:")
print(f"  p1.species = {p1.species}")
print(f"  p2.species = {p2.species}")

# 实例属性遮蔽类变量
p1.species = "Custom"
print(f"\np1.species = 'Custom' (实例遮蔽):")
print(f"  p1.species = {p1.species} (实例变量)")
print(f"  p2.species = {p2.species} (仍是类变量)")
print(f"  Person.species = {Person.species}")

# ============================================================
# 2. 三大特性:封装、继承、多态
# ============================================================
print("\n" + "=" * 70)
print("2. 三大特性:封装、继承、多态")
print("=" * 70)

# 2.1 封装
print("\n--- 2.1 封装 ---")
class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner        # 公有属性
        self._type = "savings"    # 约定保护属性 (单下划线)
        self.__balance = balance  # 私有属性 (双下划线, 名称改写)

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            return f"存入 {amount}, 余额 {self.__balance}"
        return "存入金额必须大于0"

    def withdraw(self, amount):
        if 0 < amount <= self.__balance:
            self.__balance -= amount
            return f"取出 {amount}, 余额 {self.__balance}"
        return "余额不足或金额无效"

    def get_balance(self):
        return self.__balance

    # property装饰器
    @property
    def balance(self):
        return self.__balance

    @balance.setter
    def balance(self, value):
        if value >= 0:
            self.__balance = value
        else:
            raise ValueError("余额不能为负")

acc = BankAccount("Alice", 1000)
print(f"账户持有人: {acc.owner}")
print(f"账户类型: {acc._type}")
print(f"acc.deposit(500) = {acc.deposit(500)}")
print(f"acc.withdraw(200) = {acc.withdraw(200)}")
print(f"acc.balance (property) = {acc.balance}")
acc.balance = 5000
print(f"acc.balance = 5000 -> {acc.balance}")

# 名称改写
print(f"\n名称改写: __balance -> _BankAccount__balance")
print(f"acc._BankAccount__balance = {acc._BankAccount__balance}")

# 2.2 继承
print("\n--- 2.2 继承 ---")
class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        raise NotImplementedError("子类必须实现speak方法")

    def eat(self):
        return f"{self.name} is eating"

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)  # 调用父类构造方法
        self.breed = breed

    def speak(self):
        return f"{self.name} (汪汪!)"

    def fetch(self):
        return f"{self.name} fetches the ball"

class Cat(Animal):
    def speak(self):
        return f"{self.name}: 喵喵!"

dog = Dog("Rex", "Labrador")
cat = Cat("Whiskers")
print(f"dog.speak() = {dog.speak()}")
print(f"dog.eat() = {dog.eat()}")  # 继承的方法
print(f"dog.fetch() = {dog.fetch()}")
print(f"cat.speak() = {cat.speak()}")
print(f"cat.eat() = {cat.eat()}")

# 继承链检查
print(f"\nisinstance(dog, Animal) = {isinstance(dog, Animal)}")
print(f"isinstance(dog, Dog) = {isinstance(dog, Dog)}")
print(f"isinstance(cat, Dog) = {isinstance(cat, Dog)}")
print(f"issubclass(Dog, Animal) = {issubclass(Dog, Animal)}")

# MRO (方法解析顺序)
print(f"\nDog.__mro__ = {[c.__name__ for c in Dog.__mro__]}")

# 2.3 多重继承
print("\n--- 2.3 多重继承 ---")
class Swimmer:
    def swim(self):
        return "swimming"

class Flyer:
    def fly(self):
        return "flying"

class Duck(Animal, Swimmer, Flyer):
    def speak(self):
        return f"{self.name}: 嘎嘎!"

duck = Duck("Donald")
print(f"duck.speak() = {duck.speak()}")
print(f"duck.swim() = {duck.swim()}")
print(f"duck.fly() = {duck.fly()}")
print(f"Duck.__mro__ = {[c.__name__ for c in Duck.__mro__]}")

# 2.4 多态
print("\n--- 2.4 多态 ---")
def animal_speak(animal):
    """同一个接口, 不同的表现"""
    return animal.speak()

animals = [Dog("Rex", "Lab"), Cat("Whiskers"), Duck("Donald")]
for a in animals:
    print(f"  {animal_speak(a)}")

# 2.5 抽象基类
print("\n--- 2.5 抽象基类 (abc模块) ---")
from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

    @abstractmethod
    def perimeter(self):
        pass

    def describe(self):
        return f"{self.__class__.__name__}: area={self.area():.2f}, perimeter={self.perimeter():.2f}"

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        import math
        return math.pi * self.radius ** 2

    def perimeter(self):
        import math
        return 2 * math.pi * self.radius

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

    def perimeter(self):
        return 2 * (self.width + self.height)

# 不能实例化抽象类
try:
    shape = Shape()
except TypeError as e:
    print(f"  Shape() -> TypeError: {e}")

circle = Circle(5)
rect = Rectangle(4, 6)
print(f"  {circle.describe()}")
print(f"  {rect.describe()}")

# ============================================================
# 3. 魔术方法 (Dunder Methods)
# ============================================================
print("\n" + "=" * 70)
print("3. 魔术方法 (Dunder Methods)")
print("=" * 70)

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    # 字符串表示
    def __repr__(self):
        return f"Vector({self.x}, {self.y})"

    def __str__(self):
        return f"({self.x}, {self.y})"

    # 运算符重载
    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)

    def __sub__(self, other):
        return Vector(self.x - other.x, self.y - other.y)

    def __mul__(self, scalar):
        return Vector(self.x * scalar, self.y * scalar)

    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

    def __abs__(self):
        return (self.x ** 2 + self.y ** 2) ** 0.5

    def __bool__(self):
        return self.x != 0 or self.y != 0

    def __getitem__(self, index):
        return (self.x, self.y)[index]

    def __len__(self):
        return 2

    def __iter__(self):
        yield self.x
        yield self.y

v1 = Vector(3, 4)
v2 = Vector(1, 2)
print(f"v1 = {v1}, v2 = {v2}")
print(f"v1 + v2 = {v1 + v2}")
print(f"v1 - v2 = {v1 - v2}")
print(f"v1 * 3 = {v1 * 3}")
print(f"v1 == Vector(3,4) = {v1 == Vector(3, 4)}")
print(f"abs(v1) = {abs(v1):.2f}")
print(f"bool(v1) = {bool(v1)}")
print(f"v1[0] = {v1[0]}, v1[1] = {v1[1]}")
print(f"len(v1) = {len(v1)}")
print(f"list(v1) = {list(v1)}")

# ============================================================
# 4. 描述符 (Descriptor)
# ============================================================
print("\n" + "=" * 70)
print("4. 描述符 (Descriptor)")
print("=" * 70)

class ValidatedField:
    """描述符: 验证字段值"""
    def __init__(self, name, min_value=None, max_value=None):
        self.name = name
        self.min_value = min_value
        self.max_value = max_value

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

    def __set__(self, obj, value):
        if self.min_value is not None and value < self.min_value:
            raise ValueError(f"{self.name} 不能小于 {self.min_value}")
        if self.max_value is not None and value > self.max_value:
            raise ValueError(f"{self.name} 不能大于 {self.max_value}")
        obj.__dict__[self.name] = value

class Student:
    age = ValidatedField('age', min_value=0, max_value=150)
    score = ValidatedField('score', min_value=0, max_value=100)

    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.score = score

s = Student("Alice", 20, 95)
print(f"Student: {s.name}, age={s.age}, score={s.score}")
try:
    s.age = -5
except ValueError as e:
    print(f"  设置 age=-5 -> ValueError: {e}")
try:
    s.score = 200
except ValueError as e:
    print(f"  设置 score=200 -> ValueError: {e}")

# ============================================================
# 5. 内存管理与垃圾回收
# ============================================================
print("\n" + "=" * 70)
print("5. 内存管理与垃圾回收")
print("=" * 70)

import sys
import gc

# 5.1 引用计数
print("\n--- 5.1 引用计数 ---")
a = [1, 2, 3]
print(f"创建 a = [1,2,3]")
print(f"sys.getrefcount(a) = {sys.getrefcount(a)}")  # 2 (a本身 + getrefcount的参数)

b = a
print(f"b = a 后: sys.getrefcount(a) = {sys.getrefcount(a)}")  # 3

c = [a, a]
print(f"c = [a, a] 后: sys.getrefcount(a) = {sys.getrefcount(a)}")  # 5

del b, c
print(f"del b, c 后: sys.getrefcount(a) = {sys.getrefcount(a)}")  # 2

# 5.2 垃圾回收
print("\n--- 5.2 垃圾回收 ---")
print(f"gc.isenabled() = {gc.isenabled()}")
print(f"gc.get_threshold() = {gc.get_threshold()}")  # (700, 10, 10)

# 手动触发GC
collected = gc.collect()
print(f"gc.collect() 回收了 {collected} 个对象")

# 5.3 循环引用
print("\n--- 5.3 循环引用问题 ---")
class Node:
    def __init__(self, name):
        self.name = name
        self.parent = None
        self.children = []

    def __repr__(self):
        return f"Node('{self.name}')"

    def __del__(self):
        pass  # 实际中可以在这里释放资源

# 创建循环引用
root = Node("root")
child = Node("child")
root.children.append(child)
child.parent = root

print(f"root.children = {root.children}")
print(f"child.parent = {child.parent}")
print("循环引用: root -> child -> root")
print("引用计数无法回收, 需要GC的分代回收机制处理")

# 5.4 weakref 弱引用
print("\n--- 5.4 weakref 弱引用 ---")
import weakref

class BigData:
    def __init__(self, size):
        self.data = list(range(size))

obj = BigData(1000)
ref = weakref.ref(obj)
print(f"创建弱引用 ref = weakref.ref(obj)")
print(f"ref() is obj = {ref() is obj}")  # True

del obj
print(f"del obj 后: ref() = {ref()}")  # None - 弱引用不阻止回收

# 5.5 __slots__ 优化内存
print("\n--- 5.5 __slots__ 优化内存 ---")
class PointWithDict:
    def __init__(self, x, y):
        self.x = x
        self.y = y

class PointWithSlots:
    __slots__ = ['x', 'y']
    def __init__(self, x, y):
        self.x = x
        self.y = y

p_dict = PointWithDict(1, 2)
p_slots = PointWithSlots(1, 2)
print(f"PointWithDict 内存: {sys.getsizeof(p_dict)} bytes + __dict__")
print(f"PointWithSlots 内存: {sys.getsizeof(p_slots)} bytes (无__dict__)")
print(f"hasattr(p_dict, '__dict__') = {hasattr(p_dict, '__dict__')}")
print(f"hasattr(p_slots, '__dict__') = {hasattr(p_slots, '__dict__')}")

# 5.6 dataclass (Python 3.7+)
print("\n--- 5.6 dataclass ---")
from dataclasses import dataclass, field
from typing import List

@dataclass
class Product:
    name: str
    price: float
    quantity: int = 0
    tags: List[str] = field(default_factory=list)

    def total_value(self):
        return self.price * self.quantity

prod = Product("Laptop", 999.99, 10, ["electronics", "portable"])
print(f"prod = {prod}")
print(f"prod.total_value() = {prod.total_value()}")
print(f"dataclass自动生成 __repr__, __eq__ 等")

# ============================================================
# 6. 常见面试题
# ============================================================
print("\n" + "=" * 70)
print("6. 常见面试题")
print("=" * 70)

# 面试题1: 新式类 vs 旧式类
print("\n--- 面试题1: 新式类 vs 旧式类 ---")
print("Python 3 中所有类都是新式类 (隐式继承object)")
print(f"object in Person.__mro__ = {object in Person.__mro__}")

# 面试题2: __new__ vs __init__
print("\n--- 面试题2: __new__ vs __init__ ---")
class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            print(f"  __new__: 创建新实例")
        else:
            print(f"  __new__: 返回已有实例")
        return cls._instance

    def __init__(self, value):
        self.value = value
        print(f"  __init__: 初始化 value={value}")

s1 = Singleton(1)
s2 = Singleton(2)
print(f"  s1 is s2 = {s1 is s2}")
print(f"  s1.value = {s1.value}, s2.value = {s2.value}")

# 面试题3: 类方法 vs 静态方法
print("\n--- 面试题3: @classmethod vs @staticmethod ---")
print("  @classmethod: 第一个参数是类本身(cls), 可以访问/修改类状态")
print("  @staticmethod: 没有self/cls参数, 类的命名空间下的普通函数")
print("  使用场景:")
print("    classmethod -> 工厂方法、替代构造器")
print("    staticmethod -> 工具函数, 逻辑上属于类但不依赖类状态")

# 替代构造器
class Date:
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day

    @classmethod
    def from_string(cls, date_str):
        year, month, day = map(int, date_str.split('-'))
        return cls(year, month, day)

    @staticmethod
    def is_valid_date(date_str):
        try:
            year, month, day = map(int, date_str.split('-'))
            return 1 <= month <= 12 and 1 <= day <= 31
        except:
            return False

    def __repr__(self):
        return f"Date({self.year}, {self.month}, {self.day})"

d1 = Date(2026, 7, 5)
d2 = Date.from_string("2026-07-05")
print(f"  Date(2026,7,5) = {d1}")
print(f"  Date.from_string('2026-07-05') = {d2}")
print(f"  Date.is_valid_date('2026-07-05') = {Date.is_valid_date('2026-07-05')}")

# 面试题4: property vs 属性
print("\n--- 面试题4: @property 的使用 ---")
class Temperature:
    def __init__(self, celsius=0):
        self.celsius = celsius

    @property
    def fahrenheit(self):
        return self.celsius * 9/5 + 32

    @fahrenheit.setter
    def fahrenheit(self, f):
        self.celsius = (f - 32) * 5/9

temp = Temperature(100)
print(f"  水沸点: {temp.celsius}°C = {temp.fahrenheit}°F")
temp.fahrenheit = 32
print(f"  设置 32°F -> {temp.celsius}°C")

print("\n" + "=" * 70)
print("面向对象实验完成!")
print("=" * 70)

上机输出(ECS服务器实际运行结果)

======================================================================
【面试宝典】Python 面向对象
======================================================================

======================================================================
1. 类与对象基础
======================================================================

--- 1.1 类的定义 ---
p1 = Alice (30岁)
repr(p1) = Person(name='Alice', age=30)
p1.introduce() = 我是 Alice, 今年 30 岁
Person.get_count() = 已创建 2 个 Person 对象
Person.is_adult(20) = True
Person.species = Homo sapiens

--- 1.2 实例变量 vs 类变量 ---
p1.name = Alice (实例变量)
p1.species = Homo sapiens (类变量)
p2.species = Homo sapiens (类变量)

修改 Person.species = 'Human' 后:
  p1.species = Human
  p2.species = Human

p1.species = 'Custom' (实例遮蔽):
  p1.species = Custom (实例变量)
  p2.species = Human (仍是类变量)
  Person.species = Human

======================================================================
2. 三大特性:封装、继承、多态
======================================================================

--- 2.1 封装 ---
账户持有人: Alice
账户类型: savings
acc.deposit(500) = 存入 500, 余额 1500
acc.withdraw(200) = 取出 200, 余额 1300
acc.balance (property) = 1300
acc.balance = 5000 -> 5000

名称改写: __balance -> _BankAccount__balance
acc._BankAccount__balance = 5000

--- 2.2 继承 ---
dog.speak() = Rex (汪汪!)
dog.eat() = Rex is eating
dog.fetch() = Rex fetches the ball
cat.speak() = Whiskers: 喵喵!
cat.eat() = Whiskers is eating

isinstance(dog, Animal) = True
isinstance(dog, Dog) = True
isinstance(cat, Dog) = False
issubclass(Dog, Animal) = True

Dog.__mro__ = ['Dog', 'Animal', 'object']

--- 2.3 多重继承 ---
duck.speak() = Donald: 嘎嘎!
duck.swim() = swimming
duck.fly() = flying
Duck.__mro__ = ['Duck', 'Animal', 'Swimmer', 'Flyer', 'object']

--- 2.4 多态 ---
  Rex (汪汪!)
  Whiskers: 喵喵!
  Donald: 嘎嘎!

--- 2.5 抽象基类 (abc模块) ---
  Shape() -> TypeError: Can't instantiate abstract class Shape without an implementation for abstract methods 'area', 'perimeter'
  Circle: area=78.54, perimeter=31.42
  Rectangle: area=24.00, perimeter=20.00

======================================================================
3. 魔术方法 (Dunder Methods)
======================================================================
v1 = (3, 4), v2 = (1, 2)
v1 + v2 = (4, 6)
v1 - v2 = (2, 2)
v1 * 3 = (9, 12)
v1 == Vector(3,4) = True
abs(v1) = 5.00
bool(v1) = True
v1[0] = 3, v1[1] = 4
len(v1) = 2
list(v1) = [3, 4]

======================================================================
4. 描述符 (Descriptor)
======================================================================
Student: Alice, age=20, score=95
  设置 age=-5 -> ValueError: age 不能小于 0
  设置 score=200 -> ValueError: score 不能大于 100

======================================================================
5. 内存管理与垃圾回收
======================================================================

--- 5.1 引用计数 ---
创建 a = [1,2,3]
sys.getrefcount(a) = 2
b = a 后: sys.getrefcount(a) = 3
c = [a, a] 后: sys.getrefcount(a) = 5
del b, c 后: sys.getrefcount(a) = 2

--- 5.2 垃圾回收 ---
gc.isenabled() = True
gc.get_threshold() = (700, 10, 10)
gc.collect() 回收了 0 个对象

--- 5.3 循环引用问题 ---
root.children = [Node('child')]
child.parent = Node('root')
循环引用: root -> child -> root
引用计数无法回收, 需要GC的分代回收机制处理

--- 5.4 weakref 弱引用 ---
创建弱引用 ref = weakref.ref(obj)
ref() is obj = True
del obj 后: ref() = None

--- 5.5 __slots__ 优化内存 ---
PointWithDict 内存: 48 bytes + __dict__
PointWithSlots 内存: 48 bytes (无__dict__)
hasattr(p_dict, '__dict__') = True
hasattr(p_slots, '__dict__') = False

--- 5.6 dataclass ---
prod = Product(name='Laptop', price=999.99, quantity=10, tags=['electronics', 'portable'])
prod.total_value() = 9999.9
dataclass自动生成 __repr__, __eq__ 等

======================================================================
6. 常见面试题
======================================================================

--- 面试题1: 新式类 vs 旧式类 ---
Python 3 中所有类都是新式类 (隐式继承object)
object in Person.__mro__ = True

--- 面试题2: __new__ vs __init__ ---
  __new__: 创建新实例
  __init__: 初始化 value=1
  __new__: 返回已有实例
  __init__: 初始化 value=2
  s1 is s2 = True
  s1.value = 2, s2.value = 2

--- 面试题3: @classmethod vs @staticmethod ---
  @classmethod: 第一个参数是类本身(cls), 可以访问/修改类状态
  @staticmethod: 没有self/cls参数, 类的命名空间下的普通函数
  使用场景:
    classmethod -> 工厂方法、替代构造器
    staticmethod -> 工具函数, 逻辑上属于类但不依赖类状态
  Date(2026,7,5) = Date(2026, 7, 5)
  Date.from_string('2026-07-05') = Date(2026, 7, 5)
  Date.is_valid_date('2026-07-05') = True

--- 面试题4: @property 的使用 ---
  水沸点: 100°C = 212.0°F
  设置 32°F -> 0.0°C

======================================================================
面向对象实验完成!
======================================================================



更多推荐