【C#vsPython·第一阶段】int、string、bool?Python 的类型世界有点不一样
在 C# 里,int最大能表示 2,147,483,647(约 21 亿)。超过这个数?对不起,溢出了,你得用long。
在 Python 里?2 ** 100直接算,连眼都不眨一下。Python 的int没有上限,想算多大算多大。
当我第一次用 Python 算2 ** 1000的时候,我震惊了——这在 C# 里得用BigInteger,在 Python 里就是个普通的int。
今天咱们来聊聊基本数据类型——C# 的"固定大小" vs Python 的"任意精度"。
数值类型
C# 的数值类型像一排不同大小的箱子:
byte a = 255; // 8位,0-255 short b = 32767; // 16位 int c = 2147483647; // 32位,最常用 long d = 9223372036854775807; // 64位 float e = 3.14f; // 32位 double f = 3.14; // 64位,最常用 decimal g = 3.14m; // 128位,金融计算 // 大整数(需要 using System.Numerics) BigInteger h = BigInteger.Parse("999999999999999999999999999999");Python 就简单粗暴——一个int搞定所有整数:
a = 255 b = 32767 c = 2147483647 d = 9223372036854775807 e = 2 ** 1000 # 直接算,没问题! # 浮点数 f = 3.14 # 64位双精度 g = 3.14e10 # 科学计数法 # 复数(C# 没有的) h = 3 + 4j # Python 原生支持复数| 对比项 | C# | Python |
|---|---|---|
| 小整数 | byte,short,int,long | 统一的int |
| 大整数 | 需要BigInteger | 原生支持,无上限 |
| 浮点数 | float,double,decimal | 统一的float(64位) |
| 复数 | 需要Complex结构体 | 原生支持3 + 4j |
| 溢出检查 | 会溢出(默认) | 不会溢出 |
C# 的程序员得操心"该用 int 还是 long",Python 的程序员根本不用想——反正不会溢出。
为什么 Python 的 int 没有上限?
因为 Python 的 int 是任意精度整数,它会动态分配内存来存储大数。而 C# 的 int 是固定宽度整数,存储在 CPU 寄存器里,所以有上限。
真实场景:在密码学和大数计算中,Python 的 int 无上限特性非常有用。比如计算 RSA 密钥,Python 直接用pow(a, b, m)就行,C# 得用BigInteger.ModPow()。
布尔类型
C# 的布尔就是布尔:
bool a = true; bool b = false; bool c = true && false; // false bool d = true || false; // true bool e = !true; // false // 不能直接当数字用 int x = (int)true; // 需要显式转换,结果是 1Python 的布尔...就是整数:
a = True b = False c = True and False # False d = True or False # True e = not True # False # 布尔就是整数! x = True + True # 2 y = False * 10 # 0 z = True * 5 + False # 5| 特性 | C# | Python |
|---|---|---|
| 布尔值 | true/false(小写) | True/False(首字母大写) |
| 布尔运算 | &&,||,! | and,or,not |
| 布尔参与运算 | 需要显式转换 | 自动当整数用(0/1) |
Python 的True就是 1,False就是 0,所以True + True = 2。这不是 bug,是 feature。
为什么 Python 这样设计?
因为 Python 的布尔类型是整数的子类(bool是int的子类)。这样设计的好处是:布尔值可以直接参与数学运算,不需要显式转换。
真实场景:在数据分析中,经常需要统计满足条件的数量。Python 的布尔可以直加:
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] count = sum(x > 5 for x in data) # 5(True 的个数)C# 得这样写:
var data = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; int count = data.Count(x => x > 5); // 5字符串类型
C# 的字符串:
string s1 = "Hello"; string s2 = "World"; string s3 = s1 + " " + s2; string s4 = $"{s1} {s2}"; // 插值 int len = s1.Length; // 5 string upper = s1.ToUpper(); // "HELLO" string sub = s1.Substring(1, 3); // "ell"Python 的字符串:
s1 = "Hello" s2 = "World" s3 = s1 + " " + s2 s4 = f"{s1} {s2}" # f-string(推荐) length = len(s1) # 5(函数,不是属性) upper = s1.upper() # "HELLO" sub = s1[1:4] # "ell"(切片语法)| 对比项 | C# | Python |
|---|---|---|
| 类型名 | string(首字母大写) | str(全小写) |
| 长度 | s.Length(属性) | len(s)(函数) |
| 字符串插值 | $"Hello {name}" | f"Hello {name}" |
| 子串 | s.Substring(1, 3) | s[1:4](切片) |
| 大小写 | s.ToUpper() | s.upper() |
C# 的长度是属性s.Length,Python 的长度是函数len(s)。C# 用方法调用,Python 用切片语法——各有各的优雅。
为什么 Python 用len()而不是.length?
因为 Python 的哲学是**"统一接口"**。所有序列类型(列表、元组、字符串、字典)都用len()函数,而 C# 的.Length是数组和字符串特有的。
空值
C# 的空值有"可空类型"的概念:
string s = null; int? x = null; // 可空类型 if (s == null) { } // 值类型不能为 null(除非用 Nullable<T>) // int y = null; // 编译错误Python 没有"可空类型",任何变量都可以是 None:
s = None x = None # Python 没有"可空类型"的概念 if s is None: print("s 是 None") # 但要注意类型提示 from typing import Optional def greet(name: Optional[str] = None) -> str: if name is None: return "Hello, World!" return f"Hello, {name}!"C# 的值类型默认不能为 null,得用Nullable<T>才行。Python 的任何变量都可以是 None,简单粗暴。
为什么 Python 用is None而不是== None?
因为None是一个单例对象,is比较的是对象身份,==比较的是值。用is更高效,也更符合 Python 的惯例。
类型检查和转换
// C# 类型检查 int x = 5; bool isInt = x is int; // true Type type = x.GetType(); // System.Int32 // C# 类型转换 string s = "123"; int n = int.Parse(s); // 123 bool success = int.TryParse(s, out int result); // 安全转换# Python 类型检查 x = 5 is_int = isinstance(x, int) # True type_name = type(x).__name__ # "int" # Python 类型转换 s = "123" n = int(s) # 123 # 安全转换(没有 TryParse,需要 try-except) def safe_int(s): try: return int(s), True except ValueError: return None, FalseC# 有TryParse这种安全转换,Python 没有——想安全转换就得用try-except。
真实场景:在处理用户输入时,C# 的TryParse非常方便:
string input = Console.ReadLine(); if (int.TryParse(input, out int number)) { Console.WriteLine($"你输入的是: {number}"); } else { Console.WriteLine("请输入有效的数字"); }Python 得这样写:
input_str = input("请输入数字: ") try: number = int(input_str) print(f"你输入的是: {number}") except ValueError: print("请输入有效的数字")设计哲学
C# 的哲学是类型精确——不同大小的整数用不同类型,开发者可以选择合适的类型,内存控制更精细。
Python 的哲学是简化类型——一个int搞定所有整数,开发者不需要纠结该用int还是long,数学友好,复数原生支持。
C# 像是给你一排不同大小的箱子,你得自己选合适的; Python 像是给你一个无限大的箱子,随便装。
迁移指南:C# 开发者最容易犯的错
以为 Python 的 int 会溢出:不会,Python 的 int 是任意精度的
忘记布尔就是整数:
True + True = 2是合法的以为
None等于空字符串:None、""、0、[]是不同的过度使用类型注解:Python 不需要像 C# 那样到处写类型
以为 Python 没有复数:Python 原生支持复数
3 + 4j
坑点提醒
True + True = 2——在 Python 里,布尔就是整数:
print(True + True) # 2 print(True * 10) # 10 print(False + 1) # 1浮点数精度——和 C# 一样,Python 的浮点数也有精度问题:
print(0.1 + 0.2) # 0.30000000000000004 print(0.1 + 0.2 == 0.3) # FalseNone 不等于空——None 和空字符串/空列表是不同的:
print(None == "") # False print(None == []) # False print(None is None) # True(用 is 比较)一句话总结
Python 的 int 没有大小限制,True + True 等于 2,这就是"鸭子类型"的世界。
下一篇咱们来聊聊运算符——Python 的幂运算**让数学公式可以直接翻译成代码,链式比较0 < x < 10更是 C# 梦寐以求的语法糖。
