当前位置: 首页 > 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.gsyq.cn/news/1445074.html

相关文章:

  • 解决NLP噪声难题:FuJianAscend/byt5_large_pt在TweetQA任务中的卓越表现
  • 别再手动点灯了!用STM32 HAL库+74HC595驱动数码管,解放你的GPIO口(附Proteus仿真文件)
  • TouchDevelop:零配置浏览器编程环境与可视化开发实践
  • 极端分类技术解析:从大规模标签预测到高效算法实现
  • 手把手教你用CAPL的DiagSetPrimitiveByte搞定27服务密钥填充(附完整代码)
  • 人机协同:LLM在NLP系统Bug挖掘与质量保障中的工程实践
  • 顶尖科技公司访问项目深度解析:从申请到价值转化的全攻略
  • AI爆火背后:算法、算力、数据三驾马车如何驱动智能革命?
  • Python小工具颜值UP指南:手把手教你用termcolor打造高逼格进度条和状态提示
  • .NET Gadgeteer:模块化硬件与.NET Micro Framework的快速原型开发实践
  • FPGA玩转PSRAM的RBX特性:以APS6408L为例,实现跨页访问不降速的秘诀
  • 2026大角鹿品牌背胶怎么样?大角鹿辅材是否符合国标:全方位解析大角鹿辅材实力 - 栗子测评
  • WinDiskWriter:让Mac用户轻松制作Windows启动盘的专业解决方案
  • 性能优化指南:如何为LongCat-AudioDiT选择合适的硬件和推理参数
  • 机器学习在Wi-Fi链路质量预测中的工业应用
  • 从Web到桌面:用Electron+Vue3给你的Vite项目加个‘壳‘,5分钟实现跨平台
  • 微软密码学库SymCrypt的Rust重写:内存安全与ABI兼容的工程实践
  • 终极IDM激活脚本:3种简单方法永久解锁下载管理器完整教程
  • ezygene-如何导出基因表达矩阵
  • 为什么选择PDF4QT:5个让你爱不释手的开源PDF编辑理由
  • ZMK键盘固件:如何快速打造个性化无线键盘配置
  • 手把手教你为300+车型安装openpilot:让普通汽车秒变智能驾驶座驾
  • 终极图表提取指南:使用IBM Granite 4.0 3B Vision将图表转换为结构化数据
  • STM32 CubeMX配置USART1全流程详解:从引脚分配到printf重定向,一步都不漏
  • 技术演进逻辑:从确定性到不确定性的计算范式变迁
  • 6G流体天线多址接入技术原理与PCA优化方案
  • PTA刷题实战:C语言实现一个‘无优先级’的简单计算器(附完整代码与易错点分析)
  • 如何用e1547打造你的专属数字艺术空间:三步解决内容发现难题
  • 5分钟轻松掌握:猫抓扩展让你的浏览器变身万能下载器
  • PyTorch-NPU/bert_large_uncased模型优化技巧:提升推理速度的10个方法