当前位置: 首页 > news >正文

C#转Python第1.9篇:Python 的 dict.get 一行治好我的 TryGetValue 选择困难症

上周帮同事 review 代码,看到一段 Python:

city = data.get("address", {}).get("city", "未知")

我愣了三秒——这要是在 C# 里,得写成:

string city = "未知"; if (data.TryGetValue("address", out var address) && address is Dictionary<string, object> addrDict && addrDict.TryGetValue("city", out var cityObj)) { city = cityObj.ToString(); }

五行变一行,Python 的字典操作就是这么"暴力简洁"。还有集合运算——C# 得调方法set1.Union(set2),Python 直接用运算符set1 | set2

字典创建

C# 版本:

var dict1 = new Dictionary<string, int>(); var dict2 = new Dictionary<string, int> { { "Alice", 25 }, { "Bob", 30 }, { "Charlie", 35 } }; // C# 9+ 集合初始化 var dict3 = new Dictionary<string, int> { ["Alice"] = 25, ["Bob"] = 30 }; // 从数组创建 var dict4 = new Dictionary<int, string> { [1] = "一", [2] = "二" };

Python 版本:

dict1 = {} dict2 = dict() dict3 = { "Alice": 25, "Bob": 30, "Charlie": 35 } # 从键值对列表创建 dict4 = dict([("Alice", 25), ("Bob", 30)]) # 字典推导式 dict5 = {k: v for k, v in [("Alice", 25), ("Bob", 30)]} # 从两个列表创建 keys = ["Alice", "Bob"] values = [25, 30] dict6 = dict(zip(keys, values))

C# 的字典创建得写new Dictionary<string, int>(),Python 直接{}就行。Python 还能用dict(zip(keys, values))从两个列表创建字典,这在 C# 里得写好几行。

字典操作

C# 版本:

var dict = new Dictionary<string, int>(); // 添加/修改 dict.Add("Alice", 25); // 添加(重复键会抛异常) dict["Bob"] = 30; // 添加或修改 dict.TryAdd("Charlie", 35); // 尝试添加(不抛异常) // 访问 int age = dict["Alice"]; // 直接访问(键不存在抛异常) if (dict.TryGetValue("Alice", out int val)) // 安全访问 { Console.WriteLine(val); } // 删除 dict.Remove("Alice"); // 删除指定键 bool removed = dict.Remove("Alice"); // 返回是否成功 // 判断 bool exists = dict.ContainsKey("Alice"); // 是否包含键 bool hasValue = dict.ContainsValue(25); // 是否包含值 // 遍历 foreach (var kvp in dict) { Console.WriteLine($"{kvp.Key}: {kvp.Value}"); } // 长度 int count = dict.Count;

Python 版本:

dict_obj = {} # 添加/修改 dict_obj["Alice"] = 25 # 添加或修改 dict_obj.update({"Bob": 30}) # 批量添加 # 访问 age = dict_obj["Alice"] # 直接访问(键不存在抛 KeyError) val = dict_obj.get("Alice", 0) # 安全访问(默认值) val = dict_obj.get("Alice") # 不存在返回 None # 删除 del dict_obj["Alice"] # 删除指定键 val = dict_obj.pop("Alice") # 删除并返回值 val = dict_obj.pop("Alice", 0) # 删除并返回值(不存在返回默认值) # 判断 exists = "Alice" in dict_obj # 是否包含键(运算符!) keys = list(dict_obj.keys()) # 所有键 values = list(dict_obj.values()) # 所有值 # 遍历 for key, value in dict_obj.items(): print(f"{key}: {value}") # 长度 count = len(dict_obj)
功能C#Python
安全访问TryGetValue(key, out val)dict.get(key, default)
判断键存在ContainsKey(key)key in dict
删除并返回Remove(key)返回 booldict.pop(key)返回值
遍历foreach (var kvp in dict)for k, v in dict.items()
长度dict.Countlen(dict)

Python 的dict.get(key, default)比 C# 的TryGetValue(key, out val)简洁太多了。C# 的TryGetValue还得声明一个out变量,Python 直接返回默认值。

字典推导式

C# 版本:

var dict = new Dictionary<string, int> { { "Alice", 25 }, { "Bob", 30 }, { "Charlie", 35 } }; // 过滤 var filtered = dict .Where(kvp => kvp.Value > 25) .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); // 转换 var doubled = dict .ToDictionary(kvp => kvp.Key, kvp => kvp.Value * 2);

Python 版本:

dict_obj = { "Alice": 25, "Bob": 30, "Charlie": 35 } # 过滤 filtered = {k: v for k, v in dict_obj.items() if v > 25} # 转换 doubled = {k: v * 2 for k, v in dict_obj.items()} # 反转键值 reversed_dict = {v: k for k, v in dict_obj.items()} # 合并字典 dict1 = {"a": 1} dict2 = {"b": 2} merged = {**dict1, **dict2} # Python 3.5+ merged = dict1 | dict2 # Python 3.9+

Python 的字典推导式和列表推导式语法类似——{k: v for k, v in items}。C# 的ToDictionary()写起来啰嗦多了。

集合对比

C# 版本:

var set1 = new HashSet<int> { 1, 2, 3, 4, 5 }; var set2 = new HashSet<int> { 4, 5, 6, 7, 8 }; // 集合运算 var union = new HashSet<int>(set1); // 并集 union.UnionWith(set2); // {1,2,3,4,5,6,7,8} var intersect = new HashSet<int>(set1); // 交集 intersect.IntersectWith(set2); // {4,5} var except = new HashSet<int>(set1); // 差集 except.ExceptWith(set2); // {1,2,3} // 判断 bool contains = set1.Contains(3); // 是否包含 bool isSubset = set1.IsSubsetOf(set2); // 是否子集 bool isSuperset = set1.IsSupersetOf(set2); // 是否超集

Python 版本:

set1 = {1, 2, 3, 4, 5} set2 = {4, 5, 6, 7, 8} # 集合运算(用运算符!) union = set1 | set2 # 并集 {1,2,3,4,5,6,7,8} intersect = set1 & set2 # 交集 {4,5} difference = set1 - set2 # 差集 {1,2,3} symmetric = set1 ^ set2 # 对称差集 {1,2,3,6,7,8} # 判断 contains = 3 in set1 # 是否包含(运算符!) is_subset = set1 <= set2 # 是否子集 is_superset = set1 >= set2 # 是否超集 # 去重 lst = [1, 2, 2, 3, 3, 3] unique = list(set(lst)) # [1, 2, 3](无序)

C# 的集合运算用方法调用(UnionWith()IntersectWith()),Python 直接用运算符(|&-^)。Python 的写法更接近数学表达,更优雅。

默认值处理

C# 版本:

var dict = new Dictionary<string, int>(); // 方式 1:TryGetValue if (dict.TryGetValue("Alice", out int val)) { Console.WriteLine(val); } // 方式 2:ContainsKey + 索引 if (dict.ContainsKey("Alice")) { Console.WriteLine(dict["Alice"]); } // 方式 3:TryGetValue + 默认值 int age = dict.TryGetValue("Alice", out int v) ? v : 0;

Python 版本:

dict_obj = {} # 方式 1:get age = dict_obj.get("Alice", 0) # 方式 2:in 判断 if "Alice" in dict_obj: print(dict_obj["Alice"]) # 方式 3:setdefault(不存在则设置默认值) age = dict_obj.setdefault("Alice", 0) # 方式 4:defaultdict(自动创建默认值) from collections import defaultdict dd = defaultdict(int) # 默认值为 0 dd["Alice"] += 1 # 不会 KeyError # 方式 5:Counter(计数) from collections import Counter words = ["hello", "world", "hello"] counter = Counter(words) # {'hello': 2, 'world': 1}

Python 的defaultdictCounter是 C# 没有的——它们能自动创建默认值,省去了大量if判断。

设计哲学

C# 的哲学是类型安全——泛型确保键值类型,方法调用明确,集合运算需要显式调用方法。

Python 的哲学是运算符优先——in|&等运算符,简洁语法,字典推导式一行代码创建新字典。

C# 的字典是"类型安全"的,每个操作都有明确的类型约束; Python 的字典是"灵活"的,任何可哈希对象都能做键。

更深层的原因

  • C# 的字典是哈希表实现,类型安全确保键值类型一致

  • Python 的字典也是哈希表实现,但允许任何可哈希对象做键

真实场景:在处理 JSON 数据时,Python 的字典非常方便:

import json # 解析 JSON data = json.loads('{"name": "Alice", "age": 25}') # 安全访问嵌套数据 city = data.get("address", {}).get("city", "未知") # 统计词频 text = "hello world hello python" word_count = {} for word in text.split(): word_count[word] = word_count.get(word, 0) + 1

C# 得这样写:

// 解析 JSON var data = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonString); // 安全访问嵌套数据 string city = "未知"; if (data.TryGetValue("address", out var address) && address is Dictionary<string, object> addressDict && addressDict.TryGetValue("city", out var cityObj)) { city = cityObj.ToString(); } // 统计词频 var text = "hello world hello python"; var wordCount = new Dictionary<string, int>(); foreach (var word in text.Split(' ')) { if (wordCount.ContainsKey(word)) wordCount[word]++; else wordCount[word] = 1; }

Python 的字典操作更简洁,C# 的字典操作更安全。

迁移指南:C# 开发者最容易犯的错

  1. 以为 Python 字典没有类型安全:Python 字典有类型注解,只是可选

  2. 忘记dict.get()方法:比TryGetValue简洁多了

  3. 用列表做字典键:Python 列表不可哈希,用元组代替

  4. 忘记字典推导式:Python 的杀手锏,一行代码创建新字典

  5. 以为 Python 字典无序:Python 3.7+ 字典保持插入顺序

推荐工具:用 VS Code + Python 插件,它会帮你检查字典操作的常见错误。

坑点提醒

键的类型——Python 字典的键必须是可哈希的:

dict1 = {[1, 2]: "value"} # TypeError: unhashable type: 'list' dict1 = {(1, 2): "value"} # 可以(元组是可哈希的)

字典的顺序——Python 3.7+ 字典保持插入顺序:

d = {} d["b"] = 2 d["a"] = 1 d["c"] = 3 print(list(d.keys())) # ['b', 'a', 'c'](保持插入顺序)

合并字典——Python 3.9+ 有合并运算符:

dict1 = {"a": 1} dict2 = {"b": 2} merged = dict1 | dict2 # {'a': 1, 'b': 2}

一句话总结

Python 的dict.get(key, default)比 C# 的TryGetValue简洁太多了。

下一篇咱们来聊聊元组和解包——Python 的x, y = y, x交换变量写法,是 C# 程序员梦寐以求的语法糖。


📦示例代码:C# 转 Python 全系列配套练习代码(含 48 章示例)

  • GitHub:https://github.com/LadyKiller1025/csharp-python-demos

  • Gitee:https://gitee.com/qakjhzx/csharp-python-demos

http://www.jsqmd.com/news/933735/

相关文章:

  • 告别手写公式烦恼:用Snipaste+SimpleTex.cn,截图粘贴5分钟搞定Latex代码
  • 别再手动标点了!用CVAT骨架模板+AI工具,效率提升300%的实战心得
  • 别再手动点灯了!用STM32 HAL库+74HC595驱动数码管,解放你的GPIO口(附Proteus仿真文件)
  • 解决NLP噪声难题:FuJianAscend/byt5_large_pt在TweetQA任务中的卓越表现
  • 告别网络识别混乱:Android 10/11设备WiFi固定MAC地址的完整配置指南(附AOSP修改补丁)
  • TouchDevelop:零配置浏览器编程环境与可视化开发实践
  • 跨界思维破解复杂系统:从相变与图极限理论到工程实践
  • 基于视觉语言模型的无人机自主导航系统SINGER解析
  • Sora 2医学动画的“黄金11秒”法则:基于237例临床反馈提炼的注意力峰值控制模型(附fMRI验证曲线)
  • luke-japanese-base-finetuned-ner-openmind在OpenMind平台上的性能优化秘籍:5个技巧让日语NER推理速度提升3倍
  • 极端分类技术解析:从大规模标签预测到高效算法实现
  • 手把手教你用CAPL的DiagSetPrimitiveByte搞定27服务密钥填充(附完整代码)
  • STM32F407硬件IIC读写EEPROM(AT24C02)保姆级教程,从初始化到调试
  • 人机协同:LLM在NLP系统Bug挖掘与质量保障中的工程实践
  • 应急方案:用PNP晶体管改造二极管,原理、步骤与场景详解
  • 拆解一台眼科手术激光器:达芬奇FEMTO LDV Z8内部结构和工作原理详解
  • 保姆级教程:用ROS2和Intel RealSense D405快速生成3D点云(附Rviz2可视化配置)
  • 从‘草莓识别’到‘绝缘子检测’:我是如何把一个CV课程项目包装成优秀毕业设计的?
  • 流式机器学习在工业实时监控中的应用与实战解析
  • Windows 11终极优化指南:Win11Debloat深度解析与高效配置
  • 2026年知名的工程定制瓷砖/跨境出口瓷砖/江西贴牌加工瓷砖公司对比推荐 - 品牌宣传支持者
  • 顶尖科技公司访问项目深度解析:从申请到价值转化的全攻略
  • AI爆火背后:算法、算力、数据三驾马车如何驱动智能革命?
  • 2025年实用指南:使用EdgeRemover专业工具安全卸载Microsoft Edge浏览器
  • 智能实体识别技术如何重塑体育内容推荐:从NER到知识图谱的实战解析
  • 避坑指南:InfluxDB 2.7.x部署时遇到的‘unable to open boltdb: timeout’错误如何彻底解决
  • 6款主流降AI率平台 定稿效果拉满
  • Hermes WebUI远程访问配置:安全地从外部网络连接
  • 别再只画最小系统板了!用STM32F103C8T6实战,从复位到蜂鸣器,手把手教你搭个“智能小台灯”原型
  • 超导量子比特中的电荷与磁通色散控制技术