在 Python 中,变量的值可以分为可变(mutable)和不可变(immutable)两种类型。这种特性决定了变量在赋值、修改时的行为和性能。
1. 不可变类型
不可变类型的值一旦创建,就无法改变。任何试图修改不可变对象的操作都会创建一个新的对象。以下是常见的不可变类型:
1.1 数值类型
数值类型(如 int
、float
、complex
)是不可变的。修改数值变量时,实际上是创建了一个新的对象。
x = 10
print(id(x)) # 输出:140735241234560(内存地址)
x = x + 5 # 创建一个新的整数对象
print(id(x)) # 输出:140735241234720(新的内存地址)
1.2 字符串
字符串是不可变的,任何修改操作都会生成一个新的字符串。
s = "hello"
print(id(s)) # 输出:140735241234560
s = s + " world" # 创建一个新的字符串对象
print(id(s)) # 输出:140735241234720
1.3 元组
元组是不可变的容器类型,一旦创建,其内容不能更改。
t = (1, 2, 3)
# t[0] = 10 # 报错:TypeError: 'tuple' object does not support item assignment
1.4 冻结集合
frozenset
是不可变版本的集合,一旦创建,无法修改其元素。
fs = frozenset([1, 2, 3])
# fs.add(4) # 报错:AttributeError: 'frozenset' object has no attribute 'add'
1.5 布尔值
布尔值 True
和 False
也是不可变的。
flag = True
flag = False # 这不是修改,而是创建了一个新的布尔值
1.6 字节串和 None
字节串和 None
也是不可变类型。
2. 可变类型
可变类型的值在创建后可以被修改。以下是常见的可变类型:
2.1 列表
列表是可变的,可以在原地修改其元素、添加或删除元素。
lst = [1, 2, 3]
lst[0] = 10 # 修改元素
lst.append(4) # 添加元素
print(lst) # 输出:[10, 2, 3, 4]
2.2 字典
字典是可变的,可以修改其键值对。
d = {'a': 1, 'b': 2}
d['a'] = 10 # 修改值
d['c'] = 3 # 添加新的键值对
print(d) # 输出:{'a': 10, 'b': 2, 'c': 3}
2.3 集合
集合是可变的,可以添加或删除元素。
s = {1, 2, 3}
s.add(4) # 添加元素
s.remove(2) # 删除元素
print(s) # 输出:{1, 3, 4}
2.4 自定义对象
自定义类的实例如果没有明确限制其属性,可以修改实例的属性值。
class MyClass:
def __init__(self):
self.value = 0
obj = MyClass()
obj.value = 10 # 修改属性
print(obj.value) # 输出:10
3. 可变与不可变的区别
3.1 内存管理
-
不可变类型:修改时会创建新对象,原对象不变。
-
可变类型:修改时直接在原对象上进行,不会创建新对象。
3.2 行为差异
-
不可变对象:引用在修改后指向新对象。
-
可变对象:引用在修改时仍然指向原对象。
3.3 作为字典键
-
不可变类型:具有固定的哈希值,可以作为字典的键。
-
可变类型:哈希值可能变化,不能作为字典的键。
d = {}
d[(1, 2)] = "tuple key" # 元组是不可变的,可以作为键
# d[[1, 2]] = "list key" # 报错:TypeError: unhashable type: 'list'
4. 类型判断与转换
4.1 类型判断
使用 isinstance()
判断变量的类型。
a = 1
print(isinstance(a, int)) # 输出:True 判断是否属于指定类型
str1 = 'abc'
print(isinstance(str1, (int, str))) # 输出:True 判断是否属于多个类型之一
4.2 类型转换
Python 提供了多种类型转换函数:
函数 | 说明 | 示例 |
---|---|---|
int(x) | 将 x 转换为整数类型。 | int("10") → 10 |
float(x) | 将 x 转换为浮点数类型。 | float("3.14") → 3.14 |
str(x) | 将 x 转换为字符串类型。 | str(123) → "123" |
list(x) | 将 x 转换为列表类型。 | list((1, 2, 3)) → [1, 2, 3] |
tuple(x) | 将 x 转换为元组类型。 | tuple([1, 2, 3]) → (1, 2, 3) |
set(x) | 将 x 转换为集合类型。 | set([1, 2, 3]) → {1, 2, 3} |
dict(x) | 将 x 转换为字典类型。 | dict([('a', 1), ('b', 2)]) → {'a': 1, 'b': 2} |
bool(x) | 将 x 转换为布尔类型。 | bool(0) → False ;bool("abc") → True |
frozenset(x) | 将 x 转换为冻结集合。 | frozenset([1, 2, 3]) → frozenset({1, 2, 3}) |
bytes(x) | 将 x 转换为字节串类型。 | bytes("hello", "utf-8") → b'hello' |
complex(x) | 将 x 转换为复数类型。 | complex(2) → (2+0j) |
chr(x) | 将整数 x 转换为对应的字符。 | chr(97) → 'a' |
ord(x) | 将字符 x 转换为对应的整数。 | ord('a') → 97 |
eval(x) | 将字符串 x 作为 Python 表达式进行求值并返回结果。 | eval('3 + 4') → 7 |
5. 总结
-
不可变类型:值不可修改,修改时会创建新对象。
-
可变类型:值可修改,修改时不会创建新对象。
-
类型判断:使用
isinstance()
判断变量类型。 -
类型转换:Python 提供了丰富的类型转换函数,但需注意转换的合法性。