【Python 基础全栈·第 02 篇】数据类型与运算:数字·字符串·布尔·类型转换

系列回顾:第 01 篇我们了解了 Python 的历史与设计哲学,搭建了开发环境(解释器+虚拟环境+pip+IDE),掌握了 Python 之禅与 Pythonic 风格。本篇进入 Python 的"原子世界"——数据类型与运算。数据类型是编程的基石——所有程序都是在操作数据,而数据类型决定了数据"是什么"和"能做什么"。Python 的数据类型系统有三个核心特点:动态类型(变量无类型,值有类型)、强类型(不隐式转换,1+"2"报错)、鸭子类型(看行为不看类型)。本篇涵盖四大主题:数字类型(int/float/complex/运算符/浮点陷阱)、字符串(创建/切片/方法/f-string)、布尔与None(真值表/短路求值/is None)、类型转换(显式转换/安全vs危险/类型检查)。实战项目是计算器——一个支持四则运算、括号、历史记录的命令行计算器。


在这里插入图片描述

📑 文章目录


🔢 一、数字类型:int 无溢出,float 有陷阱

1.1 三种数字类型

Python 有三种内置数字类型:

int(整数)

Python 的整数是任意精度的——不像 C/Java 的 int 有 32 位或 64 位限制,Python 的 int 可以表示任意大的整数。这是 Python 的"超能力"之一。

# 任意大的整数
x = 42
y = 10 ** 100  # 古高尔(Googol),1后面100个0
z = 2 ** 1000  # 2的1000次方,301位数

print(type(x))  # <class 'int'>

# 不同进制
dec = 42        # 十进制
bin_val = 0b101010  # 二进制 = 42
oct_val = 0o52      # 八进制 = 42
hex_val = 0x2A      # 十六进制 = 42

# 进制转换
bin(42)    # '0b101010'
oct(42)    # '0o52'
hex(42)    # '0x2a'

float(浮点数)

Python 的浮点数遵循 IEEE 754 双精度标准(64位),与 C 的 double 相同。有效数字约 15-17 位。

x = 3.14
y = 2.0e10    # 科学计数法 = 20000000000.0
z = float('inf')   # 正无穷
w = float('-inf')  # 负无穷
nan = float('nan') # 非数字

# ⚠️ 浮点精度陷阱
print(0.1 + 0.2)        # 0.30000000000000004
print(0.1 + 0.2 == 0.3) # False!

# 解决方案1:round()
print(round(0.1 + 0.2, 10) == round(0.3, 10))  # True

# 解决方案2:Decimal(精确计算)
from decimal import Decimal
print(Decimal('0.1') + Decimal('0.2') == Decimal('0.3'))  # True

complex(复数)

z = 3 + 4j
print(z.real)   # 3.0(实部)
print(z.imag)   # 4.0(虚部)
print(abs(z))   # 5.0(模 = √(3²+4²))

1.2 运算符

Python 支持丰富的运算符,按优先级从低到高:

运算符 说明 示例
+ - * / 四则运算 7/2=3.5
// 整除(向下取整) 7//2=3
% 取模 7%2=1
** 幂运算 2**10=1024
& | ^ ~ << >> 位运算 0b101 & 0b011=0b001

/ vs // 的区别——这是 Python 3 最重要的变化之一:

# Python 3
7 / 2    # 3.5(真除法,总是返回float)
7 // 2   # 3(整除,向下取整)
-7 // 2  # -4(向下取整,不是-3!)

# Python 2(已过时)
7 / 2    # 3(整数除法)
7 / 2.0  # 3.5

1.3 数字类型常见陷阱

# 陷阱1:浮点精度
0.1 + 0.2 == 0.3  # False
# 解决:round() 或 Decimal

# 陷阱2:整数除法
7 / 2   # 3.5,不是3!
# 解决:用 // 得到整数

# 陷阱3:负数取模
-7 % 3  # 2(Python取模与数学一致,不是-1)
# Python: a % b 的符号与 b 相同

# 陷阱4:is vs ==
a = 256
b = 256
a is b  # True(小整数缓存-5~256)

c = 257
d = 257
c is d  # False!超出缓存范围
c == d  # True(值相等)
# 规则:比较值用==,比较身份用is

📝 二、字符串:不可变序列 + 切片万能 + f-string

2.1 字符串创建

Python 提供四种引号创建字符串:

s1 = 'hello'          # 单引号
s2 = "world"          # 双引号(与单引号完全等价)
s3 = """多行字符串     # 三引号(保留换行和缩进)
第二行
第三行"""
s4 = 'He said "hi"'   # 单引号内用双引号
s5 = "It's mine"      # 双引号内用单引号

# 转义字符
s6 = "Hello\nWorld"   # \n换行
s7 = "Tab\there"      # \t制表符
s8 = r"C:\new\path"   # r前缀=原始字符串,\不转义

字符串是不可变的——一旦创建,内容不能修改:

s = "hello"
# s[0] = "H"  # TypeError: 'str' object does not support item assignment

# "修改"字符串 = 创建新字符串
s = "H" + s[1:]  # "Hello"

2.2 索引与切片

切片是 Python 字符串最强大的操作——一个语法 s[start:stop:step] 搞定所有子串提取:

s = "Python"

# 索引(访问单个字符)
s[0]    # 'P'(正向,从0开始)
s[-1]   # 'n'(反向,从-1开始)
s[-2]   # 'o'

# 切片(提取子串)
s[1:4]   # 'yth'(索引1到3,不含4)
s[:3]    # 'Pyt'(从头到索引2)
s[2:]    # 'thon'(从索引2到尾)
s[:]     # 'Python'(完整拷贝)

# 步长
s[::2]   # 'Pto'(每隔1个取1个)
s[1::2]  # 'yhn'(从索引1开始每隔1个)
s[::-1]  # 'nohtyP'(反转!)

# 切片不会越界
s[100:]  # ''(空字符串,不报错)
s[-100:] # 'Python'(不报错)

2.3 字符串方法

Python 字符串有 40+ 方法,记住这 10 个核心方法:

s = "  Hello, World!  "

# 大小写
s.upper()          # "  HELLO, WORLD!  "
s.lower()          # "  hello, world!  "
s.title()          # "  Hello, World!  "
s.capitalize()     # "  hello, world!  "

# 去空白
s.strip()          # "Hello, World!"(两端)
s.lstrip()         # "Hello, World!  "(左端)
s.rstrip()         # "  Hello, World!"(右端)

# 查找
s.find("World")    # 9(首次出现位置,-1=未找到)
s.count("l")       # 3(出现次数)
s.index("World")   # 9(同find,但未找到抛ValueError)

# 判断
s.startswith("  H")  # True
s.endswith("!  ")     # True
"123".isdigit()       # True
"abc".isalpha()       # True
"abc123".isalnum()    # True

# 分割与连接
"a,b,c".split(",")           # ['a', 'b', 'c']
",".join(['a', 'b', 'c'])    # "a,b,c"

# 替换
s.replace("World", "Python")  # "  Hello, Python!  "

2.4 f-string 格式化

f-string 是 Python 3.6+ 引入的格式化方式,是目前的首选方案

name = "World"
age = 25
pi = 3.14159

# 基本用法
f"Hello, {name}!"           # "Hello, World!"
f"Age: {age}"               # "Age: 25"

# 表达式
f"2 + 3 = {2 + 3}"          # "2 + 3 = 5"
f"{'hello'.upper()}"        # "HELLO"
f"{age + 1}"                # "26"

# 格式说明符
f"{pi:.2f}"                  # "3.14"(2位小数)
f"{42:08d}"                  # "00000042"(8位补零)
f"{0.85:.1%}"                # "85.0%"(百分比)
f"{12345:,}"                 # "12,345"(千分位)
f"{42:#x}"                   # "0x2a"(十六进制)
f"{42:#b}"                   # "0b101010"(二进制)

# 对齐
f"{'left':<10}"              # "left      "(左对齐10字符)
f"{'right':>10}"             # "     right"(右对齐)
f"{'center':^10}"            # " center  "(居中)

# 日期格式化
from datetime import datetime
now = datetime.now()
f"{now:%Y-%m-%d %H:%M:%S}"  # "2025-05-28 15:30:00"

🔄 三、布尔·None·类型转换

3.1 布尔类型

Python 的布尔类型只有两个值:TrueFalse(注意大写)。布尔类型是 int 的子类——True == 1False == 0

is_student = True
is_adult = False

# 布尔运算
print(True and False)   # False(与)
print(True or False)    # True(或)
print(not True)         # False(非)

# 短路求值
x = 0
# if x != 0 and 10 / x > 1:  # 不会报错!因为x!=0为False,短路跳过
#     print("ok")

# 任何值都可以做布尔判断
bool(0)       # False
bool(42)      # True
bool("")      # False
bool("hello") # True
bool([])      # False(空列表)
bool([1, 2])  # True(非空列表)
bool(None)    # False

假值(Falsy)完整列表

bool() 说明
False False 布尔假
0, 0.0, 0j False 零值
"" False 空字符串
None False 空值
[], (), {}, set() False 空容器

其他所有值都是真值(Truthy)。

3.2 None 类型

None 是 Python 的空值类型,表示"没有值"。它是一个单例对象——全局只有一个 None。

x = None
print(type(x))   # <class 'NoneType'>

# ⚠️ 判断None用is,不用==
if x is None:     # ✅ 正确
    print("x is None")
if x == None:     # ❌ 不推荐(==可被重载)
    print("x is None")

# None的常见用途
def find_item(lst, target):
    for item in lst:
        if item == target:
            return item
    return None  # 未找到返回None

result = find_item([1, 2, 3], 5)
if result is not None:
    print(f"Found: {result}")
else:
    print("Not found")

3.3 类型转换

Python 是强类型语言——不会隐式转换类型,必须显式转换:

# 安全转换
int("42")      # 42(字符串→整数)
float("3.14")  # 3.14(字符串→浮点)
str(42)        # "42"(整数→字符串)
int(3.9)       # 3(浮点→整数,截断!)
float(42)      # 42.0(整数→浮点)
bool(42)       # True
bool(0)        # False

# 危险转换(可能报错)
int("3.14")    # ValueError!不能直接转
int("hello")   # ValueError!
int(None)      # TypeError!

# 安全转换模式
def safe_int(value, default=0):
    """安全转换为整数"""
    try:
        return int(value)
    except (ValueError, TypeError):
        return default

print(safe_int("42"))      # 42
print(safe_int("3.14"))    # 0(ValueError→default)
print(safe_int("hello"))   # 0
print(safe_int(None))      # 0

3.4 类型检查

# type() —— 获取类型
x = 42
print(type(x))        # <class 'int'>
print(type(x) == int) # True

# isinstance() —— 检查类型(推荐)
print(isinstance(x, int))    # True
print(isinstance(True, int)) # True(bool是int的子类)
print(isinstance(True, bool))# True

# isinstance vs type()
# isinstance支持继承,type()不支持
# 推荐用isinstance

# type hints(类型提示,Python 3.5+)
def greet(name: str) -> str:
    return f"Hello, {name}!"

# 运行时不强制,但IDE和mypy会检查

🛠️ 实战项目:命令行计算器

"""
命令行计算器
支持:四则运算、括号、历史记录、退出
"""

import operator

class Calculator:
    def __init__(self):
        self.history = []
        self.ops = {
            '+': operator.add,
            '-': operator.sub,
            '*': operator.mul,
            '/': operator.truediv,
            '//': operator.floordiv,
            '%': operator.mod,
            '**': operator.pow,
        }

    def evaluate(self, expr: str) -> float | int | None:
        """安全求值"""
        try:
            # 只允许数字和运算符,防止代码注入
            allowed = set('0123456789+-*/.()% // **')
            if not all(c in allowed or c.isspace() for c in expr):
                print("❌ 包含非法字符")
                return None
            result = eval(expr)  # 简化版,生产环境应用ast.parse
            self.history.append((expr, result))
            return result
        except ZeroDivisionError:
            print("❌ 除零错误")
            return None
        except SyntaxError:
            print("❌ 语法错误")
            return None

    def show_history(self):
        """显示历史"""
        if not self.history:
            print("📋 暂无历史记录")
            return
        for i, (expr, result) in enumerate(self.history, 1):
            print(f"  {i}. {expr} = {result}")

    def run(self):
        """主循环"""
        print("🔢 Python 计算器")
        print("输入表达式计算,h=历史,q=退出")
        print("-" * 40)

        while True:
            try:
                expr = input(">>> ").strip()
            except EOFError:
                break

            if not expr:
                continue
            if expr.lower() == 'q':
                print("👋 再见!")
                break
            if expr.lower() == 'h':
                self.show_history()
                continue

            result = self.evaluate(expr)
            if result is not None:
                print(f"  = {result}")

if __name__ == '__main__':
    Calculator().run()

📌 第 02 篇总结

维度 核心内容
数字类型 int(无溢出) / float(有精度) / complex / 运算符 / 陷阱
字符串 不可变 / 切片万能 / 10个核心方法 / f-string首选
布尔与None Falsy值 / 短路求值 / is None / 类型转换
实战项目 命令行计算器——四则运算+括号+历史记录

三大要点

  1. int 无溢出是超能力,float 有精度是陷阱——0.1+0.2≠0.3,用 round()或 Decimal
  2. 字符串不可变,切片万能,f-string 是格式化的终极方案
  3. 动态类型=灵活,强类型=安全,鸭子类型=多态——isinstance()检查类型

第 02 篇的核心 = int无溢出(超能力) + float有精度(陷阱) + 字符串不可变+切片万能 + f-string首选 + 动态+强+鸭子类型


Python 基础全栈系列进度

篇号 主题 核心内容 状态
01 全景搭建 历史/安装/解释器/IDE/Pythonic
02 类型与运算(本文) 数字/字符串/布尔/类型转换/计算器
03 流程控制 if/for/while/推导式/猜数字 ⏳ 下一篇
04 函数与作用域 参数/返回值/闭包/装饰器/Lambda 待写
05 数据结构 列表/元组/字典/集合/推导式 待写
06 面向对象 类/继承/多态/封装/魔术方法 待写
07 模块与包 import/pip/虚拟环境/标准库 待写
08 文件与异常 读写/with/异常/上下文管理器 待写
09 高级特性 生成器/迭代器/描述符/元类 待写
10 实战工程 规范/测试/部署/项目结构 待写

下一篇预告:第 03 篇将深入流程控制——if/elif/else 条件判断/for 循环与迭代/while 循环/三元表达式/推导式/迭代器协议,实战项目是猜数字游戏


参考链接

更多推荐