Python字典核心陷阱:哈希机制、迭代安全与默认值处理详解
1. 项目概述Python字典的“常识”陷阱字典dict大概是每个Python开发者最早接触、使用最频繁的数据结构之一。从配置文件读取、API数据解析到缓存实现、对象映射字典的身影无处不在。它简单、直观、高效以至于我们常常把它当作一种“理所当然”的工具很少去深究其行为细节。然而正是这种“想当然”的信任让不少开发者包括一些有经验的程序员在关键时刻踩进坑里。这些坑往往不是语法错误而是源于对字典底层机制和设计哲学的理解偏差。今天我们就来深挖三个最容易被忽视却又极具破坏性的字典“陷阱”。这些坑我敢说90%的日常使用者都未曾真正搞懂或者即便遇到过也只是知其然而不知其所以然。理解它们不仅能帮你写出更健壮的代码更能让你对Python这门语言有更深层次的认识。2. 字典键的“可变性”幽灵与哈希机制字典之所以能实现O(1)时间复杂度的快速查找核心在于哈希表Hash Table。当你把一个键值对放入字典时Python会调用键对象的__hash__()方法来计算一个哈希值并用这个哈希值来决定数据在内存中的存储位置。这里就引出了第一个也是最根本的坑字典的键必须是“可哈希的”hashable。2.1 什么是“可哈希”不仅仅是不可变很多人的理解停留在“键必须是不可变对象比如字符串、数字、元组”。这个说法对但不完全。准确地说一个对象要可哈希必须满足两个条件在其生命周期内其哈希值通过__hash__()方法获得必须保持不变。如果两个对象相等通过__eq__()方法判断那么它们的哈希值也必须相等。为什么列表、字典、集合不能作为字典的键因为它们都是可变对象。一个列表的内容可以随时改变如果它被用作键其哈希值在内容改变后也必须改变否则基于旧哈希值存储的键值对就再也找不到了但如果哈希值变了它又无法定位到原来存储的位置。这就破坏了哈希表的基本前提。因此Python直接禁止了可变对象作为字典键。但是坑来了自定义类的实例对象默认是可哈希的并且可以作为字典键class Person: def __init__(self, name, age): self.name name self.age age p1 Person(Alice, 30) p2 Person(Alice, 30) my_dict {} my_dict[p1] Data for Alice print(p1 p2) # 输出False 默认比较内存地址 print(my_dict.get(p2)) # 输出None print(hash(p1) hash(p2)) # 输出False在上面的例子中p1和p2虽然属性相同但它们是两个不同的对象内存地址不同。默认情况下自定义类的__eq__和__hash__方法继承自object类其__eq__比较的是内存地址__hash__通常也基于内存地址计算。所以它们被视为不同的键。更大的坑在于如果你重写了__eq__方法但没有重写__hash__方法Python会怎么做class Person: def __init__(self, id_num): self.id id_num def __eq__(self, other): # 我们认为ID相同就是同一个人 return isinstance(other, Person) and self.id other.id p1 Person(123) p2 Person(123) print(p1 p2) # 输出True try: my_dict {p1: test} except TypeError as e: print(e) # 输出unhashable type: Person你会发现代码报错了错误信息是“不可哈希的类型”。这是因为当你重写了__eq__方法后Python会默认将这个类的实例标记为不可哈希除非你显式地重写__hash__方法。这是为了强制你遵守“相等对象必须有相同哈希值”的契约。如果你希望基于id属性来判断相等性和哈希就必须同时定义这两个方法class Person: def __init__(self, id_num): self.id id_num def __eq__(self, other): return isinstance(other, Person) and self.id other.id def __hash__(self): # 哈希值基于我们用于比较相等的属性 return hash(self.id) p1 Person(123) p2 Person(123) my_dict {p1: data} print(my_dict.get(p2)) # 输出data 成功找到注意一旦你将一个对象作为字典键放入就绝对不能再去修改那些参与__eq__比较或__hash__计算的属性。否则这个对象在字典里就“消失”了因为修改属性后它的哈希值或者相等性判断可能已经改变无法再定位到原来的存储槽。这是一个极其隐蔽的Bug来源。2.2 元组作为键的“相对”安全性我们常说元组是不可变的所以可以作为字典键。但这里有一个前提元组所包含的所有元素本身也必须是不可变的即可哈希的。# 合法的键 valid_key (1, hello, (2, 3)) my_dict[valid_key] ok # 非法的键 invalid_key (1, [2, 3]) # 元组包含了一个列表 try: my_dict[invalid_key] error except TypeError as e: print(e) # 输出unhashable type: list包含可变对象的元组是不可哈希的因此不能作为字典键。在复杂的数据结构中这一点需要格外小心。3. 字典在迭代过程中的“神秘”修改与内部状态第二个坑是关于字典在迭代过程中的行为。有一条广为人知的规则不要在迭代字典或其键、值、项视图时对其进行添加或删除操作。违反这条规则通常会立即引发一个RuntimeError: dictionary changed size during iteration。my_dict {a: 1, b: 2, c: 3} for key in my_dict: if key b: del my_dict[key] # RuntimeError这个错误很直接目的是防止迭代器因字典结构突变而进入不可预测的状态。但是坑往往藏在更微妙的地方。3.1 视图对象的动态性与“安全”修改的错觉Python 3 中dict.keys(),dict.values(),dict.items()返回的是“视图对象”view objects。它们是动态的会实时反映字典的变化。my_dict {a: 1, b: 2} keys_view my_dict.keys() print(list(keys_view)) # 输出[a, b] my_dict[c] 3 print(list(keys_view)) # 输出[a, b, c] 视图动态更新了视图的动态性有时会带来便利但也会制造陷阱。考虑以下场景my_dict {a: 1, b: 2, c: 3, d: 4} # 我们想删除所有值为偶数的项 for key, value in my_dict.items(): # 这里迭代的是 items() 视图 if value % 2 0: del my_dict[key] # 直接修改原字典这段代码在 Python 3 中可能不会立即报错但行为是未定义的很可能导致某些项被跳过或者引发运行时错误。因为你在迭代一个动态视图的同时改变了它背后的字典迭代器的内部索引可能会错乱。正确的做法是在迭代过程中先收集需要修改的键然后在迭代结束后再执行修改操作。my_dict {a: 1, b: 2, c: 3, d: 4} keys_to_delete [] for key, value in my_dict.items(): if value % 2 0: keys_to_delete.append(key) for key in keys_to_delete: del my_dict[key] print(my_dict) # 输出{a: 1, c: 3}或者更Pythonic的方式是使用字典推导式dictionary comprehension来创建新字典my_dict {a: 1, b: 2, c: 3, d: 4} my_dict {k: v for k, v in my_dict.items() if v % 2 ! 0} print(my_dict) # 输出{a: 1, c: 3}3.2 字典推导式与作用域的小陷阱说到字典推导式这里也有一个新手容易迷糊的点。在推导式中产生的键值对是在一个新的字典中进行填充与原字典的迭代是分离的因此是安全的。但要注意变量作用域x 10 my_dict {a: 1, b: 2} # 在推导式中我们可以访问外层的变量x new_dict {k: v x for k, v in my_dict.items()} print(new_dict) # 输出{a: 11, b: 12}这看起来没问题。但如果你在推导式内部试图给外层变量赋值或者变量名冲突就可能产生意想不到的结果虽然这与字典本身关系不大但常在此场景下发生。4. 默认值处理的“选择困难症”与性能考量第三个坑围绕着“当键不存在时我们该怎么办”这个问题展开。Python提供了多种方案但各有优劣选错了可能带来逻辑错误或性能问题。4.1dict.get(key, default)的惰性与副作用get方法是最常用的安全访问方式。它的优点是简单、无副作用。如果键存在返回值如果不存在返回指定的默认值默认为None。data {a: 100} value data.get(b, 0) # ‘b’不存在返回0 print(value) # 输出0 print(data) # 输出{a: 100} # 原字典未被修改坑点在于默认值的求值时机。get方法的第二个参数default是在函数调用前就被求值的。这意味着无论键是否存在default表达式都会被执行。def expensive_calculation(): print(执行了耗时计算) return [] # 即使键存在expensive_calculation()也会被执行 result data.get(a, expensive_calculation()) # 输出执行了耗时计算 print(result) # 输出100如果默认值的计算成本很高比如创建一个大列表、进行一次网络请求即使键存在这个开销也无法避免。这在循环中可能会成为性能瓶颈。4.2collections.defaultdict的工厂函数模式defaultdict来自collections模块它在初始化时接受一个“工厂函数”callable。当访问一个不存在的键时它会自动调用这个工厂函数生成默认值并插入字典然后返回这个值。from collections import defaultdict # 工厂函数是 list默认值是一个空列表 dd defaultdict(list) dd[fruits].append(apple) dd[fruits].append(banana) dd[vegetables].append(carrot) print(dd) # 输出defaultdict(class list, {fruits: [apple, banana], vegetables: [carrot]})defaultdict的优点是优雅特别适合用于分组、聚合操作。它的默认值是按需、惰性生成的只有键真正不存在时才会调用工厂函数避免了get方法可能带来的不必要计算。但是它也有坑改变了字典类型你的变量不再是普通的dict而是defaultdict。在某些严格的类型检查或序列化场景下可能需要处理。默认值会“污染”字典即使你只是检查一个键比如if key in dd只要用dd[key]的方式访问它就会被创建并插入默认值。这可能导致你误判字典中实际存在的数据。dd defaultdict(int) print(a in dd) # 输出False _ dd[a] # 访问不存在的键触发默认值插入 print(a in dd) # 输出True字典现在多了一个键‘a’值为0 print(dd) # 输出defaultdict(class int, {a: 0})4.3dict.setdefault(key, default)的“原子”操作setdefault方法是一个“原子”操作如果键存在返回其值如果键不存在则先将键: default插入字典再返回default。my_dict {} # 如果‘counter’不存在则设置其为0并返回0 count my_dict.setdefault(counter, 0) print(count, my_dict) # 输出0 {counter: 0} # 再次调用键已存在直接返回值 count my_dict.setdefault(counter, 100) print(count, my_dict) # 输出0 {counter: 0} # 值没有被改成100它非常适合用于初始化一个可变的值比如列表然后进行追加操作data {} # 传统冗长写法 if tags not in data: data[tags] [] data[tags].append(python) # 使用 setdefault 的简洁写法 data.setdefault(tags, []).append(blog)setdefault的坑与get类似它的default参数也是立即求值的。并且它总是会修改原字典如果键不存在的话。4.4 Python 3.8 的海象运算符:与dict.get的配合在Python 3.8及以上版本我们可以使用海象运算符walrus operator来实现一种更灵活的惰性求值模式my_dict {a: 1} # 如果‘b’不存在则计算默认值并赋值给value同时将‘b’和这个值插入字典 if (value : my_dict.get(b)) is None: value expensive_calculation() # 仅当需要时才计算 my_dict[b] value # 现在value是获取到的或新计算的值且字典已更新这种方式结合了get的无副作用检查和惰性求值的优点但语法稍显复杂。4.5 性能对比与选择指南为了更直观我们通过一个简单的性能测试和场景分析来总结如何选择方法是否修改原字典默认值求值时机典型适用场景注意事项key in dict 赋值是惰性手动控制需要明确知晓键是否存在并分别处理代码最直观但稍显冗长dict.get(key, default)否立即求值简单查询默认值计算成本低小心高成本默认值带来的性能浪费collections.defaultdict是访问时惰性访问时分组、统计、需要频繁插入同类默认值会改变字典类型访问即可能插入数据dict.setdefault(key, default)是键不存在时立即求值初始化一个键并关联可变对象如列表后立即操作同样需注意默认值成本总会返回一个值海象运算符:get可控制惰性手动控制Python 3.8需要惰性求值且可能更新字典语法较新可读性取决于团队习惯实操心得对于简单的“有则取之无则用默认值”且默认值轻量d.get(key, default)是最清晰的选择。如果你正在做类似words[word] words.get(word, 0) 1的计数操作改用defaultdict(int)会让代码简洁高效得多。当你需要确保一个键对应一个列表/集合并随后向其中添加元素时d.setdefault(key, []).append(value)是经典模式。如果默认值的构造非常昂贵如数据库连接、复杂对象务必使用惰性求值模式先in检查或使用海象运算符避免不必要的性能损失。5. 字典的“相等”比较与嵌套结构的深水区第四个坑是的我们加餐一个是关于字典比较的。我们常用来比较两个字典是否“相等”它确实会递归地比较所有键值对。d1 {a: 1, b: [2, 3]} d2 {a: 1, b: [2, 3]} d3 {b: [2, 3], a: 1} # 顺序不同 print(d1 d2) # 输出True print(d1 d3) # 输出True 字典比较不关心键的顺序问题出在嵌套的可变对象上比如列表。list1 [2, 3] list2 [2, 3] d1 {a: 1, b: list1} d2 {a: 1, b: list2} print(d1 d2) # 输出True因为 list1 list2 是 True print(d1[b] is d2[b]) # 输出False它们是不同的列表对象 # 现在修改 d1 中的列表 d1[b].append(4) print(d1) # 输出{a: 1, b: [2, 3, 4]} print(d2) # 输出{a: 1, b: [2, 3]} # d2 看起来没变 print(d1 d2) # 输出False这看起来符合预期。但考虑以下场景original_list [2, 3] d_original {data: original_list} d_copy {data: original_list} # 不是复制列表而是共享引用 print(d_original d_copy) # 输出True print(d_original[data] is d_copy[data]) # 输出True它们指向同一个列表 d_original[data].append(99) print(d_original) # 输出{data: [2, 3, 99]} print(d_copy) # 输出{data: [2, 3, 99]} # d_copy 也“意外”地被修改了 print(d_original d_copy) # 输出True 此时仍然相等坑点在于比较的是值相等而is比较的是对象标识内存地址。当两个字典包含对同一个可变对象的引用时通过任何一个引用修改该对象都会影响到所有引用它的地方。即使比较的结果为True也可能存在这种隐蔽的“副作用”关联。如果你需要一份完全独立的副本而不是共享引用的“视图”你需要进行深拷贝deep copy。import copy original_list [2, 3] d_original {data: original_list} d_deepcopy copy.deepcopy(d_original) # 深拷贝 print(d_original d_deepcopy) # 输出True print(d_original[data] is d_deepcopy[data]) # 输出False现在是两个独立的列表 d_original[data].append(99) print(d_original) # 输出{data: [2, 3, 99]} print(d_deepcopy) # 输出{data: [2, 3]} # 深拷贝不受影响注意事项dict.copy()方法创建的是浅拷贝shallow copy。新字典是新的对象但其中的值如果是可变对象仍然是原对象的引用。d1 {a: [1, 2]} d2 d1.copy() print(d1 is d2) # 输出False字典对象不同 print(d1[a] is d2[a]) # 输出True内部的列表是同一个对象 d1[a].append(3) print(d2) # 输出{a: [1, 2, 3]} # d2 也被影响了在处理嵌套了可变对象的字典时必须时刻警惕你是想要共享引用、浅拷贝还是深拷贝这直接决定了数据的独立性和修改的传播范围。6. 总结与避坑速查表字典是Python的基石理解其深层次行为是写出稳健、高效代码的关键。回顾一下我们讨论的四个主要“坑”及其核心要点键的可哈希性字典键必须是生命周期内哈希值不变的对象。自定义类作为键时若重写__eq__必须同时重写__hash__且基于相同的属性。一旦对象作为键被存入切勿修改其影响哈希或相等的属性。迭代时修改禁止在迭代字典或其视图时直接增删条目。应收集需修改的键迭代后处理或使用字典推导式创建新字典。默认值处理根据场景选择合适的方法。警惕get()和setdefault()中默认值的立即求值开销。defaultdict虽优雅但会改变类型且访问即可能插入数据。相等性与可变嵌套对象比较值相等is比较对象同一性。包含对同一可变对象引用的两个字典修改该对象会同时影响两者。需要完全独立副本时使用copy.deepcopy()而非dict.copy()浅拷贝。最后分享一个我个人的编码习惯对于任何要作为字典键的自定义类我都会问自己三个问题这个类的实例在逻辑上何时“相等”它的哈希值应该基于哪些属性计算这些属性在作为键的生命周期内是否绝对不可变想清楚这三个问题就能从根源上避免一大类隐蔽的错误。字典虽小细节见真章希望这些剖析能让你下次使用dict时更加得心应手。

相关新闻

Mate Engine:打造你的专属虚拟桌面伴侣完全指南

Mate Engine:打造你的专属虚拟桌面伴侣完全指南

Mate Engine:打造你的专属虚拟桌面伴侣完全指南 【免费下载链接】Mate-Engine A free Desktop Mate alternative with a lightweight interface and custom VRM support, though with more features. 项目地址: https://gitcode.com/gh_mirrors/ma/Mate-Engine …

2026/8/11 9:37:24 阅读更多 →
SkillLens:AI Agent技能可观测性框架,解决技能管理黑盒问题

SkillLens:AI Agent技能可观测性框架,解决技能管理黑盒问题

1. 项目缘起:当AI Agent的技能管理成为“黑盒”最近在折腾AI Agent相关的项目,一个绕不开的痛点就是技能管理。你给Agent定义了一堆技能(Skill),比如“查询天气”、“发送邮件”、“分析数据”,然后把它扔进…

2026/8/11 9:37:24 阅读更多 →
终极桌面伴侣指南:Mate Engine如何让你的电脑桌面活起来

终极桌面伴侣指南:Mate Engine如何让你的电脑桌面活起来

终极桌面伴侣指南:Mate Engine如何让你的电脑桌面活起来 【免费下载链接】Mate-Engine A free Desktop Mate alternative with a lightweight interface and custom VRM support, though with more features. 项目地址: https://gitcode.com/gh_mirrors/ma/Mate-E…

2026/8/11 9:37:24 阅读更多 →

最新新闻

构建高质量AI应用:从提示工程到RAG与质量评估的工程实践

构建高质量AI应用:从提示工程到RAG与质量评估的工程实践

最近在技术社区看到不少关于“AI大垃圾时代”的讨论,观点认为从2026年起,AI生成内容的泛滥将导致信息质量急剧下降。作为一名长期关注技术落地的开发者,我认为与其陷入对未来的担忧,不如深入探讨其背后的技术根源,并思…

2026/8/11 12:16:34 阅读更多 →
AI视频生成模型迭代评估:从技术原理到工程落地的实践框架

AI视频生成模型迭代评估:从技术原理到工程落地的实践框架

停更五天,我又回来了。这应该是我目前拍得最好的了。这句话如果出现在一个摄影师的社交媒体上,可能只是一次普通的回归宣言。但如果它出自一个AI视频生成模型——比如Runway的Gen-2,或者Pika Labs——的更新日志,那背后的含义就完…

2026/8/11 12:16:34 阅读更多 →
AI大模型与编程工具核心技术解析及实践指南

AI大模型与编程工具核心技术解析及实践指南

1. AI大模型与编程工具全景解析 在2023年的技术浪潮中,AI大模型和AI编程工具已经彻底改变了开发者的工作方式。作为亲历这场变革的技术从业者,我见证了从最初基于规则的系统到如今百亿参数大模型的跃迁过程。当前主流的大模型如GPT-4、Claude 3和国内Dee…

2026/8/11 12:16:34 阅读更多 →
Unreal Engine集成Geoserver WMTS瓦片:三维GIS与游戏引擎融合实践

Unreal Engine集成Geoserver WMTS瓦片:三维GIS与游戏引擎融合实践

1. 项目概述与核心思路 在三维地理信息与游戏引擎融合的领域,将专业的GIS服务引入到高保真的实时渲染环境中,一直是个既令人兴奋又充满挑战的课题。这次我们要聊的,就是如何把Geoserver发布的WebMapTileService(WMTS)标…

2026/8/11 12:16:33 阅读更多 →
UE5 PaperSpriteActor源码解析:从2D精灵渲染到性能优化实战

UE5 PaperSpriteActor源码解析:从2D精灵渲染到性能优化实战

1. 项目概述:为什么我们要深入PaperSpriteActor的源码?如果你正在用UE5做2D游戏,或者想把一些2D元素(比如UI图标、背景板、简单的精灵动画)无缝集成到你的3D世界里,那你大概率已经接触过Paper2D插件了。这个…

2026/8/11 12:16:33 阅读更多 →
3分钟快速安装:Microsoft Word APA第7版参考文献格式终极指南

3分钟快速安装:Microsoft Word APA第7版参考文献格式终极指南

3分钟快速安装:Microsoft Word APA第7版参考文献格式终极指南 【免费下载链接】APA-7th-Edition Microsoft Word XSD for generating APA 7th edition references 项目地址: https://gitcode.com/gh_mirrors/ap/APA-7th-Edition 你是否曾因学术论文的参考文献…

2026/8/11 12:15:33 阅读更多 →

日新闻

如何用Video2X实现专业级视频画质提升:AI视频增强完整指南

如何用Video2X实现专业级视频画质提升:AI视频增强完整指南

如何用Video2X实现专业级视频画质提升:AI视频增强完整指南 【免费下载链接】video2x A machine learning-based video super resolution and frame interpolation framework. Est. Hack the Valley II, 2018. 项目地址: https://gitcode.com/GitHub_Trending/vi/v…

2026/8/11 0:00:02 阅读更多 →
前后端分离项目中控制台与接口工具数据差异排查指南

前后端分离项目中控制台与接口工具数据差异排查指南

1. 问题现象解析:控制台与Apifox的数据差异 最近在调试一个前后端分离项目时,遇到了一个典型问题:后端服务在本地开发环境控制台能正常输出查询数据,但通过Apifox测试时却返回空结果。这种"控制台有数据,接口工具…

2026/8/11 0:00:03 阅读更多 →
AI编程实战:从Claude Code踩坑到游戏开发入门

AI编程实战:从Claude Code踩坑到游戏开发入门

1. 从“AI能帮我做游戏”到“AI让我重新学编程”最近身边不少朋友,尤其是一些非技术背景、但对游戏开发有浓厚兴趣的朋友,都在问我同一个问题:“听说现在用Claude Code这种AI编程工具,小白也能做游戏了,是真的吗&#…

2026/8/11 0:00:03 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/11 1:08:05 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/11 1:08:05 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/11 1:08:05 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/10 17:07:33 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/11 1:08:06 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/10 17:07:33 阅读更多 →