【算法工程师】—— Python 高级

Python 高级

1. 面向对象

封装

核心的手段是在类中通过双下划线来实现封装

单个下划线 _name约定为受保护,但实际可访问。双下划线 __name不能在外部直接进行访问。

python 复制代码
class Person:
    def __init__(self, name, age):
        # 双下划线实现name与age的封装,外部不能直接访问该属性
        self.__name = name
        self.__age = age

    # 公开的方法,查看私有属性
    def info(self):
        print("name: {}, age: {}".format(self.__name, self.__age))

    # 公开设置方法,用于修改私有属性
    def set_age(self, new_age):
        self.__age = new_age


person_a = Person("小明", 10)
person_a.info()
# 修改私有属性 __age
person_a.set_age(18)
person_a.info()

继承

核心:在自定义类名后加括号并写入需要继承的类名即可。

  • 调用父类的方法父类名.方法名(self, 参数1, ...),当只有一个父类时,可用super().方法名(参数1, ...),如果是多继承,调用使用super()方法或依次调用所有的被继承者对应的方法。
  • 重写父类方法:直接在子类中声明与父类的方法相同的方法名即可。
python 复制代码
class Camer:
    def __init__(self, ip):
        self.ip = ip

    def take_photo(self, person):
        return f"{person}(普通模式)"

    def get_info_c(self):
        print("相机型号:5D Mark IV")

class Phone:
    def __init__(self, number):
        self.number = number

    def call(self, numer):
        return f"呼叫:from {self.number} to {numer}"

    def get_info_p(self):
        print("电话型号:PHILIPS飞利浦")

class SmartPhone(Camer, Phone):
    def __init__(self, ip, number, brand):
        # 调用多个父类的初始化方法
        Camer.__init__(self, ip)
        Phone.__init__(self, number)
        self.brand = brand

    def use_app(self, app_name):
        return f"使用{app_name}应用"

    # 重写父类方法
    def take_photo(self, person):
        return f"{person}(美颜模式)"

xiaomi = SmartPhone("China", "12345678901", "小米")
print(xiaomi.take_photo("张三"))
print(xiaomi.call("10123456789"))
print(xiaomi.use_app("微信"))
xiaomi.get_info_c()
xiaomi.get_info_p()

# 张三(美颜模式)
# 呼叫:from 12345678901 to 10123456789
# 使用微信应用
# 相机型号:5D Mark IV
# 电话型号:PHILIPS飞利浦

多态

同一个方法调用,根据对象的类型不同,执行的逻辑也不同。

通俗理解:各个类都有自己的的方法,但这些方法名相同,不同类通过同一个函数调用这个方法会有不同的返回结果。

python 复制代码
# 父类:动物
class Animal:
    def __init__(self, name):
        self.name = name

    # 定义通用的"叫"方法(父类占位,由子类重写)
    def make_sound(self):
        pass  # 空实现,子类必须重写

# 子类:猫
class Cat(Animal):
    def make_sound(self):
        print(f"{self.name}:喵喵喵~")

# 子类:狗
class Dog(Animal):
    def make_sound(self):
        print(f"{self.name}:汪汪汪!")

# 子类:鸭子
class Duck(Animal):
    def make_sound(self):
        print(f"{self.name}:嘎嘎嘎~")

# 通用函数:接收Animal类型的对象,调用make_sound方法(多态的核心体现)
def animal_sound(animal):
    animal.make_sound()

# 测试多态效果
if __name__ == "__main__":
    # 创建不同的动物对象
    cat = Cat("橘猫")
    dog = Dog("柴犬")
    duck = Duck("小黄鸭")

    # 调用同一个函数,传入不同对象,表现出不同行为
    animal_sound(cat)   # 输出:橘猫:喵喵喵~
    animal_sound(dog)   # 输出:柴犬:汪汪汪!
    animal_sound(duck)  # 输出:小黄鸭:嘎嘎嘎~

2. 魔法方法

Python 中的魔法方法(Magic Methods / Special Methods)是以双下划线__开头和结尾 的特殊方法(比如__init____str__)。它们不是由你手动调用的,而是在特定场景下(比如创建对象、打印对象、做加法运算)由 Python 解释器自动触发执行

特点

  • 无需显式调用 :比如你写print(obj)时,Python 会自动调用obj__str__方法,不用你写obj.__str__()
  • 绑定特定语法 :每个魔法方法对应 Python 的一个基础语法或操作(比如__add__对应+运算符,__len__对应len()函数);
  • 自定义对象行为 :通过重写魔法方法,你可以让自定义的类对象支持 Python 的原生操作(比如让你的类对象能做加法、能被len()计算长度)。
  1. __init__: 创建对象时自动触发,初始化属性。

    python 复制代码
    def __init__(self, name, age):
        self.name = name
        self.age = age
        print(f"对象{self.name}已创建")
  2. __del__: 对象被销毁时自动触发(程序结束/手动删除)

    python 复制代码
    def __del__(self):
        print(f"对象{self.name}已销毁")
  3. __str__: 触发方式 print(obj)str(obj)

    python 复制代码
    def __str__(self):
        return f"Person(name={self.name}, age={self.age})"
  4. __repr__: 触发方式 ``repr(obj)终端直接输对象`

    python 复制代码
    def __repr__(self):
        return f"Person('{self.name}', {self.age})"
  5. __add__: 自定义加法逻辑, 触发方式 bj1 + obj2

    python 复制代码
    def __add__(self, other):
        # 先判断other是不是Rectangle类型,保证健壮性
        if isinstance(other, Rectangle):
            return self.area + other.area
        else:
            raise TypeError("只能和Rectangle对象相加")
  6. __sub__: 自定义减法逻辑, obj1 - obj2

  7. __eq__: 自定义 "等于" 逻辑, obj1 == obj2

    python 复制代码
    # 自定义==:年龄相同则相等
        def __eq__(self, other):
            if isinstance(other, Person):
                return self.age == other.age
            return False
  8. __gt__: 自定义 "大于" 逻辑, obj1 > obj2

    python 复制代码
    # 自定义>:年龄大则更大
        def __gt__(self, other):
            if isinstance(other, Person):
                return self.age > other.age
            raise TypeError("只能和Person对象比较")
  9. __lt__: 自定义 "小于" 逻辑, obj1 < obj2

  10. __len__: 自定义 "长度" 逻辑, len(obj)

    python 复制代码
    # 自定义len():返回成绩的数量
        def __len__(self):
            return len(self.scores)
  11. __getitem__: 自定义索引取值逻辑, obj[index]

    python 复制代码
    # 自定义索引取值:score_list[0]
        def __getitem__(self, index):
            return self.scores[index]
  12. __setitem__: 自定义索引赋值逻辑, obj[index] = value

    python 复制代码
    # 自定义索引赋值:score_list[0] = 90
        def __setitem__(self, index, value):
            # 校验成绩合法性
            if 0 <= value <= 100:
                self.scores[index] = value
            else:
                raise ValueError("成绩必须在0-100之间")
  13. __enter__: 初始化资源(比如打开文件),触发场景进入 with 代码块时

    python 复制代码
     # 进入with时触发:打开文件
        def __enter__(self):
            self.file = open(self.filename, self.mode)
            return self.file  # 给as后的变量赋值
  14. __exit__: 清理资源(比如关闭文件),触发场景退出 with 代码块时

    python 复制代码
    # 退出with时触发:关闭文件
        def __exit__(self, exc_type, exc_val, exc_tb):
            if self.file:
                self.file.close()
            print("文件已自动关闭")
  15. __call__: 允许类的实例像函数一样被调用。

    python 复制代码
    class Multiplier:
        def __init__(self, factor):
            self.factor = factor
        
        def __call__(self, x):
            """使实例可调用,返回x乘以factor的结果"""
            return x * self.factor
    
    # 创建实例
    double = Multiplier(2)
    triple = Multiplier(3)
    
    # 像函数一样调用实例
    print(double(5))    # 10
    print(triple(5))    # 15
    print(double(10))   # 20

3. 推导式

列表推导式

语法

python 复制代码
# 基础语法:无条件筛选
[表达式 for 变量 in 可迭代对象]

# 带条件筛选:只保留满足条件的元素
[表达式 for 变量 in 可迭代对象 if 条件]

# 嵌套循环:处理多层可迭代对象
[表达式 for 变量1 in 可迭代对象1 for 变量2 in 可迭代对象2]

字典推导式

语法

python 复制代码
# 基础语法
{键表达式: 值表达式 for 变量 in 可迭代对象}

# 带条件筛选
{键表达式: 值表达式 for 变量 in 可迭代对象 if 条件}

集合推导式

语法

python 复制代码
# 基础语法
{表达式 for 变量 in 可迭代对象}

# 带条件筛选
{表达式 for 变量 in 可迭代对象 if 条件}

生成器推导式

语法

python 复制代码
# 示例1:创建生成器对象
gen = (i * i for i in range(1, 11))
print(gen)  # 输出:<generator object <genexpr> at 0x...>(不是列表,是生成器)

# 示例2:遍历生成器(按需生成元素)
for num in gen:
    print(num, end=" ")  # 输出:1 4 9 16 25 36 49 64 81 100

# 示例3:大数据量场景------生成1000万个数的平方(生成器更省内存)
# 列表推导式:big_list = [i*i for i in range(10_000_000)]  # 占用大量内存
# 生成器推导式:big_gen = (i*i for i in range(10_000_000))  # 几乎不占内存

4. 装饰器

装饰器本质是一个接收函数作为参数、并返回新函数的高阶函数 ,核心作用是:在不修改原函数代码、不改变原函数调用方式的前提下,为函数添加额外功能

python 复制代码
# 定义装饰器(高阶函数+闭包)
def log_decorator(func):
    # 内层函数(闭包):包装原函数,添加额外功能
    def wrapper(*args, **kwargs):
        print(f"函数{func.__name__}开始执行...")
        result = func(*args, **kwargs)
        print(f"函数{func.__name__}执行结束,结果:{result}")
        return result
    return wrapper

# 使用语法糖@,直接装饰函数
@log_decorator  # 等价于:add = log_decorator(add)
def add(a, b):
    return a + b

@log_decorator  # 等价于:multiply = log_decorator(multiply)
def multiply(a, b):
    return a * b

# 调用方式不变
add(1, 2)		# 输出:函数add开始执行... 函数add执行结束,结果:3  3
multiply(3, 4)	# 输出:函数multiply开始执行... 函数multiply执行结束,结果:12  12

带参数的装饰器

python 复制代码
# 带参数的装饰器(三层嵌套)
def log_decorator(prefix=""):
    # 第一层:接收装饰器的参数
    def outer(func):
        # 第二层:接收被装饰的函数
        def wrapper(*args, **kwargs):
            # 第三层:包装函数,使用装饰器参数
            print(f"{prefix}函数{func.__name__}开始执行...")
            result = func(*args, **kwargs)
            print(f"{prefix}函数{func.__name__}执行结束,结果:{result}")
            return result
        return wrapper
    return outer

# 使用带参数的装饰器
@log_decorator(prefix="[日志]")  # 传入自定义前缀
def add(a, b):
    return a + b

@log_decorator()  # 不传参数,使用默认值
def multiply(a, b):
    return a * b

# 调用
add(1, 2)  # 输出:[日志]函数add开始执行... [日志]函数add执行结束,结果:3
multiply(3, 4)  # 输出:函数multiply开始执行... 函数multiply执行结束,结果:12

5. 上下文管理器

python 复制代码
# 经典用法:with + 上下文管理器
with open("test.txt", "w") as f:
    f.write("Hello Context Manager")
# 无需手动调用f.close(),with代码块结束后自动关闭文件

6. 解包操作

基础解包(无*

适用于列表、元组、字符串、range 等有序可迭代对象 ,要求变量数量和元素数量完全匹配(否则报错),是最基础的解包形式。

python 复制代码
# 1. 元组解包(最常用,Python中逗号分隔的多个值本质是元组)
tup = (1, 2)
a, b = tup  # 把元组的2个元素拆给a、b
print(a, b)  # 输出:1 2

# 2. 列表解包
lst = [3, 4]
c, d = lst
print(c, d)  # 输出:3 4

# 3. 字符串解包(按字符拆分)
s = "AB"
x, y = s
print(x, y)  # 输出:A B

# 4. 处理函数多返回值(本质是元组解包)
def get_user_info():
    return "张三", 25, "北京"  # 函数返回多个值时,默认打包成元组

name, age, city = get_user_info()  # 解包接收
print(name, age, city)  # 输出:张三 25 北京

# 注意:变量数量和元素数量不匹配会报错
# a, b = [1,2,3]  # ValueError: too many values to unpack (expected 2)
# a, b, c = [1,2]  # ValueError: not enough values to unpack (expected 3, got 2)

扩展解包(*):处理数量不匹配的情况

*符号可以接收 "剩余的所有元素"(生成一个列表),解决变量数量和元素数量不匹配的问题。*可以放在变量的开头、中间或结尾(Python3.0 + 支持),是解包中最灵活的用法。

python 复制代码
# 1. *放在结尾:接收后面所有剩余元素
a, *b = [1, 2, 3, 4]
print(a)  # 输出:1(单个变量接收第一个元素)
print(b)  # 输出:[2, 3, 4](*变量接收剩余元素,生成列表)

# 2. *放在开头:接收前面所有剩余元素
*a, b = [1, 2, 3, 4]
print(a)  # 输出:[1, 2, 3]
print(b)  # 输出:4

# 3. *放在中间:接收中间的剩余元素
a, *b, c = [1, 2, 3, 4]
print(a)  # 输出:1
print(b)  # 输出:[2, 3]
print(c)  # 输出:4

# 4. 特殊:*接收空元素(元素数量刚好匹配时)
a, *b, c = [1, 4]
print(a)  # 输出:1
print(b)  # 输出:[](空列表)
print(c)  # 输出:4

核心: * + 容器,表示将容器中的一级元素分离。

字典解包

*:解包字典的(返回可迭代的键);

**:解包字典的键值对(作为函数的关键字参数)。

python 复制代码
d = {"name": "张三", "age": 25, "city": "北京"}

# *解包字典的键(返回列表)
keys = [*d]
print(keys)  # 输出:['name', 'age', 'city']

# 遍历键值对时的解包(常用)
for k, v in d.items():  # items()返回(键,值)元组,解包给k、v
    print(f"{k}: {v}")
# 输出:
# name: 张三
# age: 25
# city: 北京
python 复制代码
def print_info(name, age, city):
    print(f"姓名:{name},年龄:{age},城市:{city}")

user_dict = {"name": "李四", "age": 30, "city": "上海"}
# 用**解包字典,等价于print_info(name="李四", age=30, city="上海")
print_info(**user_dict)  # 输出:姓名:李四,年龄:30,城市:上海

# 合并字典(Python3.5+支持)
d1 = {"a": 1, "b": 2}
d2 = {"b": 3, "c": 4}
# **解包两个字典,后面的字典覆盖前面的同名键
merged_dict = {**d1, **d2}
print(merged_dict)  # 输出:{'a': 1, 'b': 3, 'c': 4}

7. 匿名函数

基本语法

python 复制代码
lambda 参数列表: 表达式
python 复制代码
# 示例1:无参数(仅返回固定值)
print((lambda: "Hello Lambda")())  # 输出:Hello Lambda

# 示例2:带默认参数
greet = lambda name="陌生人": f"你好,{name}!"
print(greet())        # 输出:你好,陌生人!
print(greet("张三"))  # 输出:你好,张三!

# 示例3:带可变参数(*args/**kwargs)
sum_all = lambda *args: sum(args)  # 求和任意数量的参数
print(sum_all(1, 2, 3, 4))  # 输出:10

# 示例4:三元表达式(唯一支持的"条件判断"形式)
check_even = lambda x: "偶数" if x % 2 == 0 else "奇数"
print(check_even(4))  # 输出:偶数
print(check_even(5))  # 输出:奇数

8. 并行处理

进程

适用场景CPU 密集型任务:比如数学计算、数据建模、视频编码、大文件解压(需要持续占用 CPU,充分利用多核)。

关键三个语句:

  • 创建进程:p = multiprocessing.Process(target=calculate_sum, args=("P1", 0, 50000000))
  • 启动:p.start()
  • 等待结束:p.join()
python 复制代码
import multiprocessing
import time

# 定义CPU密集型任务:计算累加和
def calculate_sum(name, start, end):
    total = 0
    for i in range(start, end):
        total += i
    print(f"进程{name}计算完成:{start}到{end}的和为{total}")

if __name__ == "__main__":
    start_time = time.time()

    # 方式1:单进程(对比用)
    # calculate_sum("单进程", 0, 100000000)  # 耗时约4秒(视CPU性能)

    # 方式2:多进程(利用多核并行)
    p1 = multiprocessing.Process(target=calculate_sum, args=("P1", 0, 50000000))
    p2 = multiprocessing.Process(target=calculate_sum, args=("P2", 50000000, 100000000))

    # 启动进程
    p1.start()
    p2.start()

    # 等待进程结束
    p1.join()
    p2.join()

    end_time = time.time()
    print(f"总耗时:{end_time - start_time:.2f}秒")  # 耗时约2秒(并行,几乎减半)

进程间通信

关键三个语句:

  • 创建队列:queue = multiprocessing.Queue(maxsize=10)
  • 出队:item = queue.get()
  • 入队:queue.put(item)
python 复制代码
import multiprocessing
import time
import random

def producer(queue, name, items):
    """生产者进程:生成数据并放入队列"""
    print(f"生产者 {name} 开始工作")
    for i in range(items):
        item = f"产品-{name}-{i+1}"
        queue.put(item)
        print(f"生产者 {name} 生产了: {item}")
        time.sleep(random.uniform(0.1, 0.5))
    
    # 发送结束信号
    queue.put(None)
    print(f"生产者 {name} 结束")

def consumer(queue, name):
    """消费者进程:从队列取出并处理数据"""
    print(f"消费者 {name} 开始工作")
    end_count = 0
    
    while True:
        item = queue.get()
        
        if item is None:
            end_count += 1
            print(f"消费者 {name} 收到结束信号 ({end_count}/3)")
            if end_count >= 3:  # 有3个生产者
                break
        else:
            print(f"消费者 {name} 消费了: {item}")
            time.sleep(random.uniform(0.2, 0.3))
    
    print(f"消费者 {name} 结束")

if __name__ == '__main__':
    # 创建队列
    queue = multiprocessing.Queue(maxsize=10)
    
    # 创建生产者进程
    producers = []
    for i in range(3):
        p = multiprocessing.Process(
            target=producer,
            args=(queue, f"P{i+1}", 5)
        )
        producers.append(p)
    
    # 创建消费者进程
    consumers = []
    for i in range(2):
        c = multiprocessing.Process(
            target=consumer,
            args=(queue, f"C{i+1}")
        )
        consumers.append(c)
    
    # 启动所有进程
    for p in producers:
        p.start()
    
    for c in consumers:
        c.start()
    
    # 等待生产者完成
    for p in producers:
        p.join()
    
    # 确保消费者收到结束信号
    for _ in consumers:
        queue.put(None)
    
    # 等待消费者完成
    for c in consumers:
        c.join()
    
    print("所有进程完成!")

进程池

python 复制代码
import multiprocessing
import time
import os

def process_task(x):
    """处理任务,返回结果的平方"""
    print(f"进程 {os.getpid()} 处理任务: {x}")
    time.sleep(0.5)  # 模拟耗时操作
    return x * x

if __name__ == '__main__':
    # 创建进程池,最大进程数为4
    pool = multiprocessing.Pool(processes=4)
    
    # 准备任务数据
    tasks = list(range(1, 11))
    
    print("开始并行处理任务...")
    
    # 方法1: apply - 同步执行,阻塞直到结果返回
    print("\n1. 使用apply(同步):")
    for task in tasks[:3]:
        result = pool.apply(process_task, (task,))
        print(f"  任务 {task} 结果: {result}")
    
    # 方法2: apply_async - 异步执行
    print("\n2. 使用apply_async(异步):")
    async_results = []
    for task in tasks[3:7]:
        result = pool.apply_async(process_task, (task,))
        async_results.append((task, result))
    
    # 获取异步结果
    for task, result in async_results:
        print(f"  任务 {task} 结果: {result.get()}")
    
    # 方法3: map - 类似内置map函数
    print("\n3. 使用map:")
    results = pool.map(process_task, tasks[7:])
    for i, result in enumerate(results, start=8):
        print(f"  任务 {i} 结果: {result}")
    
    # 方法4: imap - 惰性迭代器
    print("\n4. 使用imap(惰性):")
    for i, result in enumerate(pool.imap(process_task, tasks), start=1):
        print(f"  任务 {i} 结果: {result}")
    
    # 关闭进程池
    pool.close()
    pool.join()
    print("所有任务完成!")

补充:获取CPU逻辑核心数

python 复制代码
# 获取CPU逻辑核心数(最常用,对应超线程后的核心数)
cpu_count = multiprocessing.cpu_count()
print(f"CPU逻辑核心数:{cpu_count}")

线程

适用场景IO 密集型任务:比如文件读写、网络请求(爬虫、接口调用)、数据库操作(大部分时间在等待 IO,而非占用 CPU)。

python 复制代码
import threading
import time
import requests

# 定义IO密集型任务:请求网页
def fetch_url(name, url):
    print(f"线程{name}开始请求:{url}")
    response = requests.get(url)
    print(f"线程{name}请求完成:{url}的状态码为{response.status_code}")

if __name__ == "__main__":
    start_time = time.time()

    # 方式1:单线程(对比用)
    # fetch_url("单线程", "https://www.baidu.com")
    # fetch_url("单线程", "https://www.taobao.com")
    # fetch_url("单线程", "https://www.jd.com")  # 耗时约3秒(串行等待)

    # 方式2:多线程(并发,无需等待IO)
    t1 = threading.Thread(target=fetch_url, args=("T1", "https://www.baidu.com"))
    t2 = threading.Thread(target=fetch_url, args=("T2", "https://www.taobao.com"))
    t3 = threading.Thread(target=fetch_url, args=("T3", "https://www.jd.com"))

    t1.start()
    t2.start()
    t3.start()

    t1.join()	# 等待进程结束
    t2.join()
    t3.join()

    end_time = time.time()
    print(f"总耗时:{end_time - start_time:.2f}秒")  # 耗时约1秒(并发,几乎并行)

线程池

python 复制代码
import time
from concurrent.futures import ThreadPoolExecutor

def task(num):
    """简单任务:休眠1秒后返回数字的平方"""
    time.sleep(1)
    return num * num

if __name__ == "__main__":
    # 创建线程池(3个线程)
    executor = ThreadPoolExecutor(max_workers=3)

    # 提交单个任务,获取Future对象
    future1 = executor.submit(task, 2)
    future2 = executor.submit(task, 3)

    # 方式1:阻塞获取结果(直到任务完成)
    print(f"任务1结果:{future1.result()}")  # 输出:4
    print(f"任务2结果:{future2.result()}")  # 输出:9

    # 方式2:判断任务状态
    print(f"任务1是否完成:{future1.done()}")  # 输出:True
    print(f"任务1是否取消:{future1.cancelled()}")  # 输出:False

    # 关闭线程池
    executor.shutdown()

协程

适用场景超高 IO 密集型任务:比如高并发爬虫、实时通信、微服务接口(需要处理上万 / 百万级 IO 请求)。

python 复制代码
import asyncio
import aiohttp  # 异步HTTP库(需先安装:pip install aiohttp)
import time

# 定义异步IO任务:请求网页
async def fetch_url(name, url):
    print(f"协程{name}开始请求:{url}")
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            print(f"协程{name}请求完成:{url}的状态码为{response.status}")

# 主协程
async def main():
    # 创建多个协程任务
    tasks = [
        fetch_url("C1", "https://www.baidu.com"),
        fetch_url("C2", "https://www.taobao.com"),
        fetch_url("C3", "https://www.jd.com"),
        # 可扩展到上千个协程,依然高效
    ]
    # 并发执行所有协程
    await asyncio.gather(*tasks)

if __name__ == "__main__":
    start_time = time.time()

    # 运行异步程序
    asyncio.run(main())

    end_time = time.time()
    print(f"总耗时:{end_time - start_time:.2f}秒")  # 耗时约1秒(比多线程更高效)

9. 异常检测

try-except-finally

python 复制代码
# 示例:读取文件,无论是否出错都关闭文件
file = None
try:
    file = open("test.txt", "r")
    content = file.read()
    print(content)
except FileNotFoundError as e:
    print(f"错误:{e}")
finally:
    # 无论是否出错,都关闭文件
    if file:
        file.close()
        print("文件已关闭")

捕获所有异常

python 复制代码
try:
    # 任意可能出错的代码
    lst = [1,2]
    print(lst[3])
except Exception as e:
    # 捕获所有运行时异常
    print(f"未知错误:{type(e).__name__} - {e}")

主动抛出异常

python 复制代码
def check_age(age):
    if not isinstance(age, int):
        # 主动抛出TypeError,自定义错误信息
        raise TypeError("年龄必须是整数!")
    if age < 0 or age > 120:
        # 主动抛出ValueError
        raise ValueError("年龄必须在0-120之间!")
    return age

# 测试
try:
    check_age(-5)
except (TypeError, ValueError) as e:
    print(f"参数校验失败:{e}")  # 输出:参数校验失败:年龄必须在0-120之间!

10. 断言

语法

python 复制代码
assert 条件表达式 [, 自定义错误信息]
python 复制代码
def calculate_area(radius):
    # 断言:半径必须是正数(调试阶段校验)
    assert isinstance(radius, (int, float)), f"半径必须是数字,当前类型:{type(radius)}"
    assert radius > 0, f"半径必须大于0,当前值:{radius}"
    return 3.14 * radius * radius

# 调试阶段:参数错误会立刻报错
calculate_area(-2)  # 触发AssertionError: 半径必须大于0,当前值:-2
calculate_area("abc")  # 触发AssertionError: 半径必须是数字,当前类型:<class 'str'>
相关推荐
sheji34162 小时前
【开题答辩全过程】以 基于python的图书销售数据可视化系统为例,包含答辩的问题和答案
开发语言·python·信息可视化
程序猿Code2 小时前
groovy闭包
开发语言·python
2401_861412142 小时前
python 从入门到精通 高清PDF 背记手册
开发语言·python·pdf
幻云20102 小时前
Python机器学习:筑基与实践
前端·人工智能·python
喵手2 小时前
Python爬虫零基础入门【第二章:网页基础·第2节】你要抓的到底是什么:HTML、CSS 选择器、XPath 入门?
爬虫·python·python爬虫实战·python爬虫工程化实战·python爬虫零基础入门·网页基础·网页结构解析
lsx2024062 小时前
jEasyUI 条件设置行背景颜色
开发语言
小毅&Nora2 小时前
【Java线程安全实战】⑭ ForkJoinPool深度剖析:分治算法的“智能厨房“如何让并行计算跑得更快
java·算法·安全
飞天小蜈蚣2 小时前
python-django_ORM的十三个查询API接口
开发语言·python·django
飞雪20072 小时前
局域网服务发现技术, DNS-SD和mDNS具体有什么区别, 什么不同?
开发语言·局域网·mdns·airplay·dns-sd·airprint