深入解析Python typing模块:Union与Optional的实战应用与区别

Python中typing库中 Union 和 Optional 的具体区别 【代码】Python中typing库中 Union 和 Optional 的具体区别。 阅读详情

1. 为什么你需要关心Union和Optional?

如果你写过一段时间的Python,尤其是参与过稍微有点规模的团队项目,你肯定遇到过这种情况:拿到一个别人写的函数,光看参数名字,完全猜不透它到底要传什么进去。一个叫 value 的参数,它可以是字符串吗?可以是数字吗?可以是列表吗?或者,它能不能不传?为了搞清楚,你不得不去翻函数内部的实现代码,或者去问写这个函数的人,甚至可能因为传错了类型,在运行时才报错,耽误半天功夫。

这就是Python动态类型带来的“甜蜜的负担”。它写起来灵活自由,但代码一复杂,维护和协作就成了噩梦。而 typing 模块,就是Python官方给我们的一剂“后悔药”,它允许我们给变量、函数参数、返回值加上类型提示,让代码的意图像说明书一样清晰。

今天我们不聊 typing 模块的全貌,就聚焦两个最常用、也最容易让人困惑的类型:Union 和 Optional。我见过不少新手,甚至一些有经验的开发者,对它们的理解都停留在“好像差不多”的层面。其实,它们一个像“多选题”,一个像“可空单选题”,用对了地方,代码的健壮性和可读性能提升一大截。

简单来说,Union 解决的是“这个变量可能是A类型,也可能是B类型”的问题。比如,一个处理用户输入的函数,输入既可能是字符串(来自网页表单),也可能是整数(来自API调用)。而 Optional 解决的是“这个变量可能有值,也可能是空的(None)”的问题。比如,一个查询数据库的函数,找到了就返回结果对象,没找到就返回 None。

理解它们的区别,不仅能让你写出更规范的代码,还能让你更好地利用像 Pylance、Mypy 这样的静态类型检查工具,在写代码的阶段就提前发现潜在的类型错误,把Bug扼杀在摇篮里。接下来,我们就抛开枯燥的概念,用一堆我实际踩过的坑和总结出来的最佳实践,带你彻底搞懂它们。

2. Union:当你的变量拥有“多重身份”

2.1 Union的基本语法与直观理解

Union 的用法非常直白。我们从 typing 模块导入它,然后用方括号 [] 把可能的类型列出来。

from typing import Union

def process_input(data: Union[str, int, list]) -> str:
    # 函数体...

上面这个类型提示 Union[str, int, list] 就是在大声告诉所有读这段代码的人(包括未来的你,以及像PyCharm这样的IDE):“注意了!我这个 data 参数,它可以是字符串、整数或者列表,其他类型一概不接受!”

我最早用 Union 是在处理第三方API返回值的时候。有些API设计得比较“随性”,同一个字段,成功时返回一个对象字典,失败时返回一个错误信息字符串。那时候还没用类型提示,每次处理这个返回值都得小心翼翼地用 isinstance() 做类型判断,代码写得又臭又长。后来上了 Union,代码立刻清爽了:

from typing import Union, Dict

def handle_api_response(response: Union[Dict[str, str], str]) -> None:
    if isinstance(response, dict):
        print(f"操作成功,返回数据: {response['data']}")
    else:
        print(f"操作失败,错误信息: {response}")

# 使用示例
handle_api_response({"status": "ok", "data": "user_123"})  # 传字典
handle_api_response("Error: Authentication failed")         # 传字符串
# handle_api_response(123)  # 如果传数字,IDE(如VS Code with Pylance)会给出类型警告!

看到最后一行注释了吗?这就是类型提示的威力。在你运行代码之前,IDE就能用波浪线提醒你:“老兄,你这里可能传错了类型哦!” 这比运行到一半才报 AttributeError 或者 KeyError 要友好太多了。

2.2 超越基础:Union的进阶玩法与常见陷阱

你以为 Union 就是简单列几个类型?在实际项目中,它的玩法可多了,坑也不少。

场景一:处理多种数字类型。 这是 Union 最经典的场景之一。数学计算函数经常要同时处理 int 和 float。

from typing import Union

def normalize(value: Union[int, float], max_val: Union[int, float]) -> float:
    """将value归一化到[0, 1]区间,基于max_val。"""
    # 注意:这里直接进行除法,Python会自动处理int/float的转换
    return float(value) / float(max_val)

print(normalize(5, 10))    # 输出: 0.5
print(normalize(3.0, 7))   # 输出: 0.42857142857142855

但这里有个细节:函数的返回值我标注成了 float。因为无论输入是 int 还是 float,除法运算的结果几乎总是 float(除了 0/任何数)。这样标注更精确。

场景二:兼容新旧数据格式。 在迭代系统时,我们常常需要让一段代码同时支持老数据格式和新数据格式。

from typing import Union, List, TypedDict

# 旧格式:一个简单的字符串列表,表示用户标签
# 新格式:一个字典列表,每个字典包含标签名和权重
class TagDict(TypedDict):
    name: str
    weight: float

def calculate_tag_score(tags: Union[List[str], List[TagDict]]) -> float:
    total_score = 0.0
    if tags and isinstance(tags[0], str):
        # 处理旧格式:每个标签默认权重为1.0
        total_score = len(tags) * 1.0
    elif tags and isinstance(tags[0], dict):
        # 处理新格式:累加权重
        for tag in tags:
            total_score += tag.get('weight', 0.0)
    return total_score

# 可以同时处理两种数据
old_tags = ["python", "coding", "blog"]
new_tags = [{"name": "python", "weight": 1.5}, {"name": "coding", "weight": 1.0}]
print(calculate_tag_score(old_tags))  # 输出: 3.0
print(calculate_tag_score(new_tags))  # 输出: 2.5

踩坑提醒:Union 类型判断的顺序很重要! 在上面的例子中,我首先检查 isinstance(tags[0], str)。如果我把顺序反过来,先检查 dict,那么 List[str] 也会被 isinstance(tags[0], dict) 判断吗?不会,因为字符串不是字典实例。但这里有个更隐蔽的坑:如果 tags 是空列表 [],那么 tags[0] 会引发 IndexError。所以更健壮的写法是先判断 tags 是否非空,或者使用 try...except。在实际代码中,你需要根据具体情况选择最安全的判断逻辑。

场景三:与 Literal、Callable 等复杂类型联用。 Union 可以包含任何有效的类型提示。

from typing import Union, Literal, Callable

# 一个配置项,可以是几个特定的字符串,也可以是一个返回字符串的函数
ConfigValue = Union[Literal["auto", "high", "low"], Callable[[], str]]

def get_config(setting: ConfigValue) -> str:
    if isinstance(setting, str):
        return setting
    else: # 此时setting一定是一个可调用对象
        return setting()

# 使用
print(get_config("auto"))                     # 输出: auto
print(get_config(lambda: "dynamic_value"))    # 输出: dynamic_value

这种用法在框架或库的设计中非常常见,它提供了极大的灵活性,同时又通过类型提示约束了灵活性的边界。

3. Optional:优雅地处理“空”值

3.1 Optional的本质就是Union[Type, None]

很多教程会告诉你 Optional[int] 就等价于 Union[int, None]。没错,从本质上讲,Optional 只是一个语法糖,是为了一个极其常见的场景(值可能为 None)而提供的便捷写法。导入 Optional 后,你可以这样写:

from typing import Optional

def find_user(username: str) -> Optional[dict]:
    # 模拟数据库查询
    user_database = {"alice": {"age": 30}, "bob": {"age": 25}}
    return user_database.get(username)  # .get()方法找不到时返回None

user = find_user("alice")
if user is not None:
    print(f"找到用户,年龄:{user['age']}")
else:
    print("用户不存在")

这段代码清晰表达了函数的契约:我给你一个用户名,我可能返回一个用户字典,也可能返回 None(表示没找到)。调用者看到这个类型签名,就会立刻意识到需要对 None 情况进行处理。

我强烈建议,任何可能返回 None 的函数,都应该使用 Optional 明确标注出来。这是一个对代码读者极其友好的习惯。想象一下,你调用一个叫 get_data() 的函数,如果它的返回值类型只写了 dict,你会默认它永远返回字典。一旦它在某些情况下返回 None,而你又没做判断,程序就会崩溃。如果它被标注为 Optional[dict],这就是一个醒目的警告牌,提醒你“这里可能有坑,请小心驾驶”。

3.2 实战:Optional在数据验证与配置读取中的应用

Optional 的用武之地远比想象中多。

场景一:带有默认值的函数参数。 这是 Optional 最经典的模式。参数可以传一个值,也可以不传(即使用默认值),在函数内部,我们经常用 if param is None: 来判断。

from typing import Optional

def create_message(content: str, priority: Optional[int] = None) -> str:
    """创建消息,可选优先级。"""
    msg = f"[INFO] {content}"
    if priority is not None:
        # 注意:这里确保了priority不是None后才进行数值比较
        if priority > 5:
            msg = f"[URGENT] {content}"
        elif priority < 0:
            msg = f"[LOW] {content}"
    return msg

print(create_message("系统启动完成"))  # 输出: [INFO] 系统启动完成
print(create_message("磁盘空间不足", priority=8))  # 输出: [URGENT] 磁盘空间不足
print(create_message("例行备份", priority=-1))  # 输出: [LOW] 例行备份

注意,我们把默认值设为了 None(priority: Optional[int] = None)。这意味着调用者可以省略这个参数。在函数内部,我们通过 if priority is not None: 来检查是否传入了有效值。千万不要用 if not priority: 来判断,因为如果传入的 priority 是整数 0,if not priority: 也会为真,这会导致逻辑错误。

场景二:解析可能缺失的配置。 从配置文件(如JSON, YAML)或环境变量读取配置时,很多项是可选的。

import os
from typing import Optional

class AppConfig:
    def __init__(self):
        # 必选项
        self.host: str = os.getenv("APP_HOST", "localhost")
        # 可选项,可能为None
        self.port: Optional[int] = self._parse_optional_int("APP_PORT")
        self.debug_mode: Optional[bool] = self._parse_optional_bool("APP_DEBUG")

    def _parse_optional_int(self, env_var: str) -> Optional[int]:
        value = os.getenv(env_var)
        if value is None:
            return None
        try:
            return int(value)
        except ValueError:
            print(f"警告:环境变量 {env_var} 的值 '{value}' 无法转换为整数,将使用None。")
            return None

    def _parse_optional_bool(self, env_var: str) -> Optional[bool]:
        value = os.getenv(env_var)
        if value is None:
            return None
        return value.lower() in ('true', '1', 'yes')

config = AppConfig()
print(f"Host: {config.host}, Port: {config.port}, Debug: {config.debug_mode}")

# 使用配置时,需要检查可选值
if config.port is not None:
    print(f"将在端口 {config.port} 上启动服务...")
else:
    print("使用默认端口配置。")

在这个例子中,port 和 debug_mode 被明确定义为 Optional,真实地反映了“它们可能没有配置”的业务逻辑。后续代码在用到它们时,都必须先进行判空,这强制我们写出了更安全的代码。

场景三:链式调用中的安全导航。 在处理嵌套的、可能为 None 的对象时,Optional 能帮你理清思路。

from typing import Optional

class User:
    def __init__(self, name: str, profile: Optional['Profile'] = None):
        self.name = name
        self.profile = profile

class Profile:
    def __init__(self, website: Optional[str] = None):
        self.website = website

def get_user_website(user: Optional[User]) -> Optional[str]:
    """安全地获取用户的网站地址。如果任何一环为None,则返回None。"""
    if user is None or user.profile is None:
        return None
    return user.profile.website

# 模拟数据
user1 = User("Alice", Profile("https://alice.com"))
user2 = User("Bob")  # 没有Profile
user3 = None  # 用户对象本身可能就是None

print(get_user_website(user1))  # 输出: https://alice.com
print(get_user_website(user2))  # 输出: None
print(get_user_website(user3))  # 输出: None

虽然Python没有像其他语言那样的“安全导航运算符”(如 user?.profile?.website),但通过 Optional 类型提示和清晰的条件判断,我们完全可以实现同样的效果,并且逻辑一目了然。

4. Union vs Optional:核心区别与如何选择

到现在,你应该对两者各自的能力有了了解。那到底什么时候用 Union,什么时候用 Optional 呢?我们通过一个对比表格和具体场景来剖析。

特性Union[TypeA, TypeB, ...]Optional[Type]
核心含义“多选一”:变量可以是列举的多种类型中的任意一种。“可有可无”:变量可以是一个特定类型,也可以是 None。
语法本质多种类型的联合。Union[Type, None] 的语法糖。
典型场景函数需要处理多种不同格式的输入数据;API字段在不同情况下类型不同。函数可能找不到结果而返回None;函数的某个参数是可选的。
内部处理通常需要 isinstance() 或 type() 来判断具体是哪种类型,然后分别处理。通常只需要用 is None 或 is not None 判断值是否存在。
给人的暗示关注点是“类型”的多样性。调用者需要准备好处理不同的数据类型。关注点是“值”的存在性。调用者需要准备好处理值缺失的情况。

选择指南:

  1. 如果你的变量“没有值”是一种正常、有效的状态,并且这种状态用 None 表示,那么就用 Optional。 这是最直接的判断。查询失败、配置缺失、可选参数,这些场景的语义都是“可能有,可能无”,None 完美代表了“无”的状态,所以 Optional 是不二之选。
  2. 如果你的变量可以有多种不同的、有意义的值类型,而这些类型都不是 None,那么就用 Union。** 比如一个解析器,输入可以是文件路径(字符串)或者已经打开的文件对象(IO对象)。字符串和文件对象都是有效的、有意义的类型,不能用 None 来代表其中一种,所以用 Union[str, IO]。
  3. 一个常见的混淆点:Union[Type, None] 和 Optional[Type] 完全等价,但社区更倾向于使用 Optional 来表达“可空”的语义。 因为 Optional 更简洁,意图更明确。看到 Optional,人们立刻想到“可空”;看到 Union[Type, None],可能需要反应一下。所以,只要是涉及 None 的场景,无脑用 Optional 就对了。
  4. 小心“三态”场景: 有时候你会遇到一个变量可以是类型A、类型B,或者 None。这时候就是 Union 和 Optional 的结合体了。正确的写法是 Union[TypeA, TypeB, None],或者,如果你觉得 None 是主要语义之一,也可以写成 Optional[Union[TypeA, TypeB]]。两者等价,但后者的可读性可能稍好一点,它强调了“首先,这是一个可空的值;其次,它的非空值可以是A或B”。
from typing import Union, Optional

# 场景:一个缓存函数,键可以是字符串或整数,如果缓存未命中则返回None
def get_from_cache(key: Union[str, int]) -> Optional[object]:
    cache = {"a": 1, 1: "one"}
    return cache.get(key)  # .get() 方法在键不存在时返回None

# 返回值类型 Optional[object] 明确表示:可能返回一个任意对象,也可能返回None。

# 更复杂的三态变量:一个设置项,可以是"on"(str), "off"(str), 或者是None(表示使用默认)
SettingValue = Optional[str]  # 这样写对吗?不对!因为None和"on"/"off"语义不同。
# 正确写法:
SettingValue = Union[Literal["on", "off"], None]
# 或者,更清晰的:
SettingValue = Optional[Literal["on", "off"]]
# 意思是:非空值只能是字面量“on”或“off”,或者为None。

5. 让类型提示发挥真正价值:工具与最佳实践

仅仅写上 Union 和 Optional 是不够的,你得让它们“活”起来,为你检查错误。这就需要静态类型检查工具。

5.1 配置Mypy进行静态检查

Mypy是Python生态中最主流的静态类型检查器。安装它:pip install mypy。然后,你可以在命令行中检查你的代码文件。

假设我们有一个 buggy_example.py 文件,里面有一些类型问题:

# buggy_example.py
from typing import Union, Optional

def add(a: Union[int, float], b: Union[int, float]) -> Union[int, float]:
    return a + b

result = add("hello", 5)  # 错误:第一个参数是字符串,不是int/float

def greet(name: Optional[str]) -> str:
    return f"Hello, {name.upper()}"  # 危险:如果name是None,这里会抛AttributeError

greet(None)  # 触发上面的危险

在终端运行 mypy buggy_example.py,Mypy会给出非常详细的错误报告:

buggy_example.py:6: error: Argument 1 to "add" has incompatible type "str"; expected "Union[int, float]"  [arg-type]
buggy_example.py:10: error: Item "None" of "Optional[str]" has no attribute "upper"  [union-attr]
Found 2 errors in 1 file (checked 1 source file)

第一个错误指出了错误的函数调用。第二个错误非常关键,它发现了我们函数内部的一个潜在运行时错误:我们直接调用了 name.upper(),但没有检查 name 是否为 None。Mypy拯救了我们一次潜在的崩溃!

5.2 在IDE中实时获得反馈

如果你使用 Visual Studio Code 并安装了 Pylance 扩展,或者使用 PyCharm,它们都能在你写代码的时候,实时分析类型提示并给出警告或错误提示。就像有个经验丰富的同事在旁边随时审核你的代码一样。我个人的工作流已经离不开这个了,它能极大地减少低级错误。

5.3 我总结的几条最佳实践

  1. 渐进采用:不要试图一下子给所有代码加上类型提示。可以从新代码、核心模块、公共API开始,逐步铺开。
  2. 保持精确:尽量使用最精确的类型。比如,如果一个函数真的永远返回 float,就不要把返回值写成 Union[int, float]。
  3. 善用 TypeAlias:对于复杂的、重复使用的 Union 或 Optional 类型,可以用 TypeAlias 给它们起个别名,提高可读性。
    from typing import Union, TypeAlias
    
    JsonValue: TypeAlias = Union[str, int, float, bool, None, list['JsonValue'], dict[str, 'JsonValue']]
    # 现在 JsonValue 就可以代表一个标准的JSON可序列化的值类型
    
  4. None 检查要显式:处理 Optional 类型时,总是使用 is None 或 is not None 进行显式比较。
  5. 不要过度使用 Union:如果一个函数参数可以是太多类型(比如超过3种),可能意味着函数职责不单一,需要考虑重构了。
  6. 文档与类型提示互补:类型提示说明了“是什么类型”,但复杂的业务逻辑“为什么”这么做,还是需要靠文档字符串(Docstring)来解释。两者结合,代码才能既清晰又易懂。

从我自己的经验来看,在团队中推行类型提示,初期可能会觉得有点麻烦,但一旦习惯,代码的维护成本、新人上手速度、以及整体的可靠性都会有质的提升。Union 和 Optional 作为其中最常用的两种工具,值得你花时间彻底掌握。下次当你犹豫一个参数该不该加 Optional 时,就想想,如果调用者忘了处理 None 情况,会不会导致程序崩溃?如果会,那就果断加上。

Python类型提示与typing模块详解 类型系统是现代编程语言的核心概念之一,它通过定义变量和函数的类型约束来提高代码的可靠性和可维护性。Python作为动态类型语言,通过类型提示(Type Hints)和typing模块实现了渐进式类型化,在不牺牲灵活性的前提下获得了静态类型检查的优势。这一机制基于PEP 484提案实现,允许开发者使用注解语法为函数参数、返回值等添加类型信息。在实际工程中,类型提示能够与mypy等静态检查工具配合,显著减少类型相关错误,特别适合大型项目和团队协作场景。typing模块提供了从基础类型到泛型容器等丰富支持,是Py 阅读详情

相关推荐

Python 3.12+ 类型提示与None:Optional[T] 的3种实战用法解析

本文详细解析了Python 3.12+中类型提示与None的实战用法,重点介绍了Optional[T]、Union[T, None]和T | None三种表示法的工程实践。通过具体代码示例和最佳实践建议,帮助开发者更好地处理可能为None的值,提升代码的可读性和类型安全性。

diejiankuai3444的博客 316

深入解析Python typing模块:Union与Optional的实战应用对比

本文深入解析Python typing模块中Union与Optional的实战应用对比,帮助开发者理解类型提示的重要性。通过具体代码示例,展示Union处理多类型变量和Optional处理可能为None值的最佳实践,提升代码可读性和可维护性。

weixin_26908317的博客 369

Python typing实战:从函数签名到CI门禁的类型契约工程

Python作为动态语言,天然缺乏编译期类型约束,导致运行时隐性错误频发,如None穿透、字符串误参与数值计算等。typing module通过静态类型提示机制,在不改变运行行为的前提下,构建可验证的接口契约。其核心价值在于提升协作确定性与故障拦截前置性——借助mypy等检查器,在编码阶段即发现类型不匹配,而非等待线上报错。典型应用场景包括API参数校验、数据管道字段保障、跨模块调用契约定义等。本文聚焦真实项目落地路径,详解函数签名优先策略、TypedDict结构化字典、Protocol鸭子类型协议及渐进式

a1311010193的博客 366

python -typing模块之Optional类

python -typing模块之Optional类

weixin_44226291的博客 7912

Python中None的深入解析与最佳实践

在Python编程中,None作为表示空值或缺失值的特殊单例对象,其底层实现和正确使用方式对代码质量和性能有重要影响。从内存管理角度看,Python解释器启动时即创建None对象,所有引用共享同一内存地址,这使得`is None`比较比`== None`更高效。在类型系统中,Optional和Union类型注解能明确表达可能返回None的意图,而PEP 8风格指南推荐使用`is None`进行判断。实际开发中,None常见于函数默认返回值、字典操作和Pandas数据处理等场景。正确处理None值能避免可变默

congjukun0600的博客 356

第一弹:llama.cpp编译

1.编译llama.cpp命令行(电脑版本);2.交叉编译安卓命令行版本。

joedan0104的专栏 1万+

python函数注释 typing模块函数类型注解(函数注解)(指定函数参数和返回值类型)Union注解、Callable注解、Optional可变参数注解。类型提示、类型注解、参数注释(参数类型)

因此,set(“dsf234fdsf”)的结果是一个包含字符串中每个字符的集合:{‘3’, ‘s’, ‘2’, ‘d’, ‘f’, ‘4’}。在函数get_unique_numbers中,参数numbers被注解为List[int],表示它应该是一个整数类型的列表。然而,当你调用get_unique_numbers(“dsf234fdsf”)时,你传递给函数的参数是一个字符串,而不是一个整数列表。Python的typing模块提供了一种在函数定义中添加类型注解的方式,用于指定函数参数和返回值的类型。

Dontla的博客 7852

深度强化学习-D3QN算法原理与代码

Dueling Double Deep Q Network(D3QN)算法结合了Double DQN和Dueling DQN算法的思想,进一步提升了算法的性能。如果对Doubel DQN和Dueling DQN算法还不太了解的话,可以参考我的这两篇博文:深度强化学习-Doubel DQN算法原理与代码和深度强化学习-Dueling DQN算法原理与代码,分别详细讲述了这两个算法的原理以及代码实现。本文就带领大家了解一下D3QN算法,代码链接见下方。 代码:https://github.com/indigo

weixin_46133643的博客 2万+

python中typing.Union 用法

1. python可以传递两种参数,返回值也可以是多种 通常一个参数和返回值只能是一个类型,在c/c++,java,golang这种静态语言里,也不可能返回两种类型,或者传参使用两种类型,但是在python里可以。 def mytest(a:str or int)->str or int:   return a*2 2. python 使用Uinon的写法 from typing import Union def mytest(a:Union[str,int])->Union[str,i

高压锅博客 1万+

Plant Simulation 实战指南:从二次分配问题到优化布局设计

本文是一份Plant Simulation实战指南,详细讲解了如何利用该仿真软件解决工厂布局中的二次分配问题。通过从数据准备、模型搭建到集成遗传算法进行自动化优化的完整流程,帮助工程师在数字孪生环境中高效寻找最优设备布局方案,从而显著降低物流成本,提升生产效率。

i1j2k的博客 564

[工具使用]黑暗引擎FOFA

黑暗引擎FOFAFOFA(点我进入)逻辑运算符搜索子域名domain搜索指定内容的host全部域名bodycert搜索选定应用的网站搜索指定开放端口的IP搜索指定协议的IP搜索IP或者网段的信息搜索指定CSS/JS网站常用的一些内容其他 FOFA(点我进入) 官网这样描述:FOFA是白帽汇推出的一款网络空间资产搜索引擎。它能够帮助用户迅速进行网络资产匹配、加快后续工作进程。例如进行漏洞影响范围分析、应用分布统计、应用流行度排名统计等。 简单理解就是,一个本土加强版shodan,知道某产品在互联网的部署情况、

网络安全知识分享 3万+

Python - typing 模块 —— Optional

前言 typing 是在 python 3.5 才有的模块 前置学习 Python 类型提示:https://www.cnblogs.com/poloyy/p/15145380.html 常用类型提示 https://www.cnblogs.com/poloyy/p/15150315.html 类型别名 https://www.cnblogs.com/poloyy/p/15153883.html...

qq_33801641的博客 4610

某招标公告网和vcaptcha验证码识别逆向

本文分析了某验证码系统的加密流程及破解思路。首先通过反混淆技术定位到加密函数,拆解了包含指纹函数、环境参数等组成的加密字符串。研究发现验证码生成涉及canvas指纹、环境检测等反爬机制,可通过模拟浏览器环境绕过。验证过程需要解密图片顺序,通过work2.js计算还原图片位置,再结合滑动轨迹、时间等参数生成验证请求。文章仅提供技术研究思路,强调需遵守法律法规,严禁非法破解信息系统。完整流程包括环境模拟、加密参数还原、图片处理和轨迹生成等步骤,成功率较高。

码王吴彦祖的博客 578

Python类型提示:Union和Optional的5个实战用法(附代码示例)

本文深入探讨了Python类型提示中Union和Optional的5个核心实战用法,涵盖API响应解析、数据库操作、配置管理等场景。通过具体代码示例,展示了如何利用typing模块提升代码可读性与健壮性,帮助开发者编写更专业、更易维护的Python项目。

weixin_29229989的博客 319

SAP CPI 之使用国密算法实现SM系列算法加解密

System.out.println("SM2-私钥:" + privateKey);System.out.println("SM2-公钥:" + publicKey);System.out.println("SM2-密文:" + encrypts);System.out.println("SM2-明文:" + data2);新建groovy,通过import之后,调用jar包中的方法。在CP中导入jar包,选择Upload,选中导入的jar包。的密钥和向量值,不安全!的公钥和私钥,不安全!

u012830826的博客 1335

RH850从0搭建Autosar开发环境【7】- Davinci Configurator之CanTp模块配置详解(上)

RH850从0搭建Autosar开发环境【7】- Davinci Configurator之CanTp模块配置详解(上)

weixin_42412049的博客 2297

别再混淆了!Python中Union和Optional的区别与最佳实践

本文深入解析Python中Union和Optional类型提示的核心区别与最佳实践。Union用于表达“多选一”的类型联合,而Optional专为“有或无”的可空场景设计,本质是Union[Type, None]的语义化语法糖。文章通过实战案例揭示了常见误用陷阱,并提供了类型收窄、工具链集成等专业建议,帮助开发者编写更清晰、健壮的Python代码。

corn8的博客 207

YOLOv11改进策略【卷积层】| 引入注意力卷积模块RFAConv,关注感受野空间特征 助力yolov11精度提升

RFAConv:创新空间注意力和标准卷积运算感受野空间特征是针对卷积核设计的,根据卷积核大小动态生成。以3×3卷积核为例,它由非重叠滑动窗口组成,每个窗口代表一个感受野滑块。

Limiiiing的博客 1823

python typing optional_python – 我应该如何使用Optional类型提示?

可选[…]是Union […,None]的简写符号,告诉类型检查器需要特定类型的对象,或者需要None. …代表任何有效的类型提示,包括复杂的复合类型或更多类型的Union [].每当你有一个默认值为None的关键字参数时,你应该使用Optional.所以对于你的两个例子,你有dict和list容器类型,但是a关键字参数的默认值表明也允许None,所以使用Optional […]:from typ...

weixin_39930557的博客 3560

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

别再混淆了!Python中Union和Optional的正确使用姿势(附常见错误分析)

本文深入解析Python类型系统中Union和Optional的正确使用方法,帮助开发者避免常见错误。通过实战案例和类型检查技巧,展示如何有效处理多态性和可选值场景,提升代码质量与可维护性。特别适合正在使用Python typing模块的开发者阅读。

zero1的博客 634

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

别再混用Union和Optional了!Python类型标注避坑指南(3.10+版本)

本文深入解析Python 3.10+版本中Union和Optional类型标注的区别与最佳实践,帮助开发者避免常见混淆和静态类型检查错误。通过实战案例展示如何正确使用Optional表示可能为None的值,以及Union处理多种类型的场景,提升代码可读性和类型安全性。

oo7890的博客 362

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Python 3.12+ 可选类型 (Optional) 实战:5 个场景告别 None 滥用

本文探讨了Python 3.12+中Optional类型的实战应用,通过5个典型场景展示如何避免None滥用问题。文章详细介绍了Optional类型的基础用法、静态类型检查配置,以及在数据库查询、配置处理、函数式编程等场景中的最佳实践,帮助开发者编写更健壮、可维护的Python代码。

weixin_30764883的博客 416

Python 3.9 升级实战:类型系统、graphlib 与原生泛型深度解析

Python 类型提示是静态类型检查的核心机制,其演进深刻影响代码可维护性与 IDE 智能体验;graphlib 作为标准库新增的图算法模块,为依赖解析、CI/CD 编排等工程场景提供轻量可靠的拓扑排序能力。从 PEP 484 到 PEP 604(UnionType)、PEP 585(内置容器泛型),Python 3.9 实现了类型系统从‘注释辅助’到‘运行时可感知’的关键跃迁。它不仅提升 mypy 和 Pylance 的推断精度,更通过 dict[str, int] 等原生泛型写法统一类型元数据表达,显著

angel192939的博客 672

Python模块化开发实战:从脚本到工程的天气查询应用构建

在软件开发中,模块化是一种将复杂系统分解为独立、可复用组件的核心设计思想。其原理在于通过高内聚、低耦合的设计原则,将功能按职责分离,定义清晰的接口进行通信。这种架构的价值在于显著提升代码的可读性、可维护性和可测试性,便于团队协作与功能扩展。在Python开发领域,模块化是工程化实践的基石,广泛应用于Web后端、数据分析和自动化工具等场景。本文以构建一个天气查询与数据分析命令行工具为例,深入探讨如何运用模块化思想,将数据获取、解析、分析和展示等逻辑拆分为独立的‘功能积木’,并通过清晰的接口协同工作,从而打造结

weixin_33801856的博客 392

UNION与UNION ALL:从执行计划到性能优化的完全指南

在SQL集合运算中,UNION和UNION ALL都用于垂直合并两个查询结果集,但两者在去重逻辑、执行计划与性能表现上存在显著差异。UNION会隐式执行类似SELECT DISTINCT的去重操作,常引发排序或哈希运算,进而导致临时表溢出和磁盘I/O激增;UNION ALL则直接拼接结果,速度更快但可能包含重复行。理解这些底层机制,不仅有助于优化大规模数据查询,还能避免因隐式类型转换、NULL语义或列顺序错位导致的“假重复”问题。此外,Oracle、MySQL、PostgreSQL对UNION的实现各有特性

diaoju3333的博客 384
上一篇: 光伏电站一次调频技术解析|从原理到实现的完整方案
下一篇: 饥荒联机版手动添加树苗资源的存档修改指南
github5actions
博客等级 码龄1天 0粉丝 1824原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值