目录

第二章:变量与数据类型

本章目标

完成本章学习后,你将能够:

变量基础

什么是变量

在编程中,变量是用于存储数据的命名位置。可以将变量看作是一个贴有标签的盒子,盒子里装着数据。

# 变量赋值
name = "Alice"
age = 25
pi = 3.14159

Python的变量模型

Python的变量与其他语言不同。在Python中:

# 图解:变量与对象
a = [1, 2, 3]  # a指向列表对象
b = a          # b也指向同一个列表对象
b.append(4)    # 修改列表
print(a)       # [1, 2, 3, 4] —— a也变了!

内存示意:

变量a ──→ [1, 2, 3, 4] ←── 变量b

变量命名规则

1. 只能包含字母、数字、下划线
2. 不能以数字开头
3. 不能是Python关键字
4. 区分大小写
# 合法变量名
name = "Alice"
_name = "private"
name2 = "Bob"
user_name = "Charlie"
UserName = "David"  # 不同变量
 
# 非法变量名
2name = "error"     # SyntaxError:不能以数字开头
my-name = "error"   # SyntaxError:不能包含连字符
my name = "error"   # SyntaxError:不能包含空格
class = "error"     # SyntaxError:关键字

Python关键字

以下单词是Python保留的,不能用作变量名:

import keyword
print(keyword.kwlist)
# ['False', 'None', 'True', 'and', 'as', 'assert', 'async', 
#  'await', 'break', 'class', 'continue', 'def', 'del', 
#  'elif', 'else', 'except', 'finally', 'for', 'from', 
#  'global', 'if', 'import', 'in', 'is', 'lambda', 
#  'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 
#  'try', 'while', 'with', 'yield']

基本数据类型

Python有以下基本数据类型:

类型 名称 示例 说明
int 整数 42, -100, 0 任意精度整数
float 浮点数 3.14, -0.5 双精度浮点数
bool 布尔值 True, False 逻辑值
str 字符串 “hello” 文本数据
NoneType 空值 None 表示无值

整数(int)

Python的整数可以任意精度,只受限于可用内存。

# 整数定义
a = 42
b = -100
c = 0
 
# 不同进制
binary = 0b1010      # 二进制,等于10
octal = 0o777        # 八进制,等于511
hexadecimal = 0xFF   # 十六进制,等于255
 
# 大整数(Python自动处理)
big_number = 123456789012345678901234567890
print(big_number * big_number)  # 不会溢出!
 
# 类型检查
print(type(a))  # <class 'int'>

浮点数(float)

Python的float是双精度浮点数(IEEE 754标准,64位)。

# 浮点数定义
pi = 3.14159
negative = -0.5
scientific = 1.5e-3   # 科学计数法,等于0.0015
 
# 浮点数精度问题
print(0.1 + 0.2)  # 0.30000000000000004,不是精确的0.3!
 
# 解决方案:使用decimal模块
from decimal import Decimal
a = Decimal('0.1')
b = Decimal('0.2')
print(a + b)  # 0.3,精确计算
 
# 无穷大和NaN
inf = float('inf')
neg_inf = float('-inf')
not_a_number = float('nan')

布尔值(bool)

布尔类型只有两个值:TrueFalse

# 布尔值
flag = True
empty = False
 
# 布尔运算
print(True and False)   # False
print(True or False)    # True
print(not True)         # False
 
# 比较运算产生布尔值
print(5 > 3)   # True
print(5 == 3)  # False
 
# 类型实际上是int的子类
print(isinstance(True, int))  # True
print(True + True)            # 2(True等于1)
print(False * 10)             # 0(False等于0)

空值(None)

None 表示 absence of a value(无值)。

# None表示没有值
result = None
 
# 函数默认返回值
def do_nothing():
    pass
 
print(do_nothing())  # None
 
# 检查是否为None
if result is None:
    print("还没有结果")
 
# 注意:不要用 == 检查None,要用 is
print(result == None)   # True,但不推荐
print(result is None)   # True,推荐方式

类型检查与转换

type()函数

# 检查变量类型
print(type(42))        # <class 'int'>
print(type(3.14))      # <class 'float'>
print(type("hello"))   # <class 'str'>
print(type(True))      # <class 'bool'>
print(type(None))      # <class 'NoneType'>

isinstance()函数

# 检查是否为特定类型
print(isinstance(42, int))           # True
print(isinstance(3.14, (int, float))) # True,检查多个类型
 
# isinstance vs type
class Animal:
    pass
 
class Dog(Animal):
    pass
 
dog = Dog()
print(type(dog) == Animal)    # False
print(isinstance(dog, Animal)) # True,考虑继承

类型转换

# 转换为整数
print(int(3.14))      # 3,截断小数部分
print(int("42"))      # 42
print(int("1010", 2)) # 10,二进制转十进制
print(int(3.9))       # 3,不是四舍五入!
 
# 转换为浮点数
print(float(42))      # 42.0
print(float("3.14"))  # 3.14
 
# 转换为字符串
print(str(42))        # "42"
print(str(3.14))      # "3.14"
print(str(True))      # "True"
print(str([1, 2, 3])) # "[1, 2, 3]"
 
# 转换为布尔值
print(bool(1))        # True
print(bool(0))        # False
print(bool("hello"))  # True,非空字符串
print(bool(""))       # False,空字符串
print(bool([1, 2]))   # True,非空列表
print(bool([]))       # False,空列表

可变对象与不可变对象

这是Python中最重要的概念之一

不可变对象(Immutable)

创建后不能被修改的对象:

# 整数不可变
a = 5
print(id(a))  # 140735890123456
a = a + 1     # 创建新对象
print(id(a))  # 140735890123488,不同的地址!
 
# 字符串不可变
s = "hello"
# s[0] = "H"  # TypeError: 'str' object does not support item assignment
s = "H" + s[1:]  # 创建新字符串
print(s)  # "Hello"

可变对象(Mutable)

创建后可以修改的对象:

# 列表可变
lst = [1, 2, 3]
print(id(lst))     # 4334567890
lst.append(4)      # 修改原对象
print(id(lst))     # 4334567890,相同地址!
print(lst)         # [1, 2, 3, 4]
 
lst[0] = 100       # 修改元素
print(lst)         # [100, 2, 3, 4]

深浅拷贝

由于可变对象的特性,有时需要创建副本:

import copy
 
# 浅拷贝
original = [1, [2, 3], 4]
shallow = original.copy()  # 或 list(original) 或 original[:]
 
original[0] = 100
print(shallow[0])  # 1,不变
 
original[1][0] = 200
print(shallow[1])  # [200, 3],变了!因为内部列表是共享的
 
# 深拷贝
deep = copy.deepcopy(original)
original[1][1] = 300
print(deep[1])     # [200, 3],不变

Python内存管理

引用计数

Python使用引用计数来管理内存:

import sys
 
a = [1, 2, 3]
print(sys.getrefcount(a))  # 2(a的引用 + getrefcount的参数引用)
 
b = a
print(sys.getrefcount(a))  # 3
 
del b
print(sys.getrefcount(a))  # 2

当对象的引用计数降为0时,内存会被回收。

垃圾回收

对于循环引用,Python使用垃圾回收器(GC)

import gc
 
# 手动运行垃圾回收
gc.collect()
 
# 查看垃圾回收统计
print(gc.get_stats())
 
# 禁用/启用垃圾回收
gc.disable()
# ... 做一些性能敏感的操作 ...
gc.enable()

小整数缓存

Python缓存了小整数(-5到256):

a = 100
b = 100
print(a is b)  # True,同一个对象
 
c = 1000
d = 1000
print(c is d)  # False(在某些Python实现中可能是True)

字符串驻留

Python会驻留(intern)一些字符串:

a = "hello"
b = "hello"
print(a is b)  # True
 
c = "hello world!"
d = "hello world!"
print(c is d)  # False,长字符串不一定驻留
 
# 手动驻留
e = sys.intern("hello world!")
f = sys.intern("hello world!")
print(e is f)  # True

变量作用域

LEGB规则

Python按以下顺序查找变量:

# 示例
x = "global"  # G
 
def outer():
    x = "enclosing"  # E
 
    def inner():
        x = "local"  # L
        print(x)     # 输出 "local"
 
    inner()
    print(x)         # 输出 "enclosing"
 
outer()
print(x)             # 输出 "global"

global和nonlocal

count = 0
 
def increment():
    global count    # 声明使用全局变量
    count += 1
 
increment()
print(count)  # 1
 
def outer():
    value = 10
 
    def inner():
        nonlocal value  # 使用外层函数的变量
        value = 20
 
    inner()
    print(value)  # 20
 
outer()

本章练习

1. 类型检测器:编写程序接收用户输入,判断并输出其数据类型 2. 温度转换器:编写程序在摄氏、华氏、开尔文温度之间转换 3. 内存探秘:使用id()函数验证可变与不可变对象的行为差异 4. 深浅拷贝实验:创建一个包含多层嵌套的列表,验证深浅拷贝的区别 5. 变量交换:不使用临时变量,交换两个变量的值

本章小结

本章我们深入学习了:

理解可变与不可变对象是掌握Python的关键,这将帮助你避免许多常见的编程错误。

下一章:第三章:运算符与表达式