Python基础(二)

1、可变与不可变

Python中,变量的值分为可变(mutable)或 不可变(immutable),该特征决定了变量在赋值、修改时的行为和性能。

1.1 不可变类型

不可变类型的值一旦创建,就无法改变。任何试图修改不可变对象的操作都会创建一个新的对象。常见不可变类型包括:

1.1.1 数值类型:int、float、complex

数字的值一旦赋值,不能被修改。

x = 10
print(id(x), hex(id(x)))
x = x + 5  # 会创建一个新的整数对象,并将其赋值给 x
print(id(x), hex(id(x)))
# 两次id不一样
# id():获取变量引用的内存地址;
# hex():转换为16进制;

1.1.2 字符串

字符串是不可变的,任何试图修改字符串内容的操作都会生成一个新的字符串。

s = "hello"
print(id(s))
s = s + " world"  # 创建一个新的字符串对象并赋值给 s
print(id(s))

 1.1.3 元组

元组是不可变的容器类型,一旦创建,其内容不能更改。

t = (1, 2, 3)
t[0] = 10  
# 会抛出 TypeError: 'tuple' object does not support item assignment

1.1.4 冻结集合

frozenset 是不可变版本的集合,一旦创建,无法修改其元素。

fs = frozenset([1, 2, 3])
fs.add(4)  
# 会抛出 AttributeError: 'frozenset' object has no attribute 'add'

1.1.5 布尔值

布尔值 TrueFalse 也属于不可变类型。

flag = True
flag = False 
# 这不是修改,而是创建了一个新的布尔值并赋值给flag

1.1.6 字节串和None

字节串和None为不可变类型。

1.2 可变类型

可变类型的值在创建后可以被修改。常见的可变类型:

1.2.1 列表

列表是可变的,可以在原地修改其元素、添加或删除元素。

lst = [1, 2, 3]
lst[0] = 10  # 修改原列表的元素
lst.append(4)  # 添加新的元素

1.2.2 字典

字典也是可变类型,可以修改其键值对。

d = {'a': 1, 'b': 2}
d['a'] = 10  # 修改字典中键 'a' 对应的值
d['c'] = 3   # 添加新的键值对

 1.2.3 集合

集合是可变的,可以添加或删除元素。

s = {1, 2, 3}
s.add(4)  # 添加元素
s.remove(2)  # 删除元素

 1.2.4 自定义对象

自定义类的实例如果没有在类中明确限制其属性,可以修改实例的属性值,因此对象实例也是可变的。

class MyClass:
    def __init__(self):
        self.value = 0

obj = MyClass()
obj.value = 10  # 修改对象的属性

1.3 可变与不可变的区别

1.3.1 内存管理

  • 对不可变类型改值时,Python会创建一个新的对象,并将该对象的引用赋给原来的变量。

  • 对可变类型修改内容时,不会创建新的对象,而是直接在原地进行修改。

import copy

# 这里是重新赋值,不是对内存空间里面的值进行修改
scoresB = [5, 6, 7, 8, 9]
print(scoresA)

scoresA = [1, 2, 3, 4, [100, 200, 300]]
# 浅拷贝:复制scoreA,不再是直接引用
scoresB = scoresA.copy()

print(id(scoresA), id(scoresB))
scoresA[4][1] = 666
print(scoresA[4][1]) # 666
print(scoresB[4][1])

# 深拷贝:完全拷贝,不会改变原数据
scoresA = [1, 2, 3, 4, [100, 200, 300]]
scoresB = copy.deepcopy(scoresA)
scoresA[4][1] = 666
print(scoresA[4][1])# 666
print(scoresB[4][1])

1.3.2 行为差异

  • 不可变对象的引用在修改后总会指向一个新对象,而可变对象的引用在修改时仍然指向原始对象。

# 不可变类型
a = 100
b = a
a = 200
print(a, b)

# 可变类型
scoresA = [1, 2, 3, 4]
scoresB = scoresA
scoresA[3] = 666
print(scoresB)

 1.3.3 作为字典的键

  • 不可变类型具有固定的哈希值,可以作为字典的键。

  • 可变类型哈希值可能变化,不能作为字典的键。

d = {}
d[(1, 2)] = "tuple key"  # 元组是不可变的,可以作为字典的键
d[[1, 2]] = "list key"   # 会抛出 TypeError: unhashable type: 'list'

特别注意

以上是基于修改而不是赋值,重新赋值操作都会指向新的对象引用。

1.4 类型判断

使用isinstance判断类型变量

a = 1
print(isinstance(a, int))
# 判断是否属于指定类型
# True

str1 = 'abc'
print(isinstance(str1, (int, str))) 
# 判断是否属于多个类型之一
# True

1.5 类型转换

这里只是总结一下常见类型转换的函数:

函数 说明 示例
int(x) x 转换为整数类型。 int("10")10
float(x) x 转换为浮点数类型。 float("3.14")3.14
str(x) x 转换为字符串类型。 str(123)"123"
list(x) x 转换为列表类型,x 必须是可迭代对象。 list((1, 2, 3))[1, 2, 3]
tuple(x) x 转换为元组类型,x 必须是可迭代对象。 tuple([1, 2, 3])(1, 2, 3)
set(x) x 转换为集合类型,x 必须是可迭代对象。 set([1, 2, 3]){1, 2, 3}
dict(x) x 转换为字典类型,x 必须是可迭代的键值对序列(如列表、元组)。 dict([('a', 1), ('b', 2)]){'a': 1, 'b': 2}
bool(x) x 转换为布尔类型,x 的值可以是任何对象,返回 TrueFalse bool(0)Falsebool("abc")True
frozenset(x) 将 x 转换为冻结集合,x 必须是可迭代对象。 frozenset([1, 2, 3])frozenset({1, 2, 3})
bytes(x) 将 x 转换为字节串类型,x 可以是字符串、字节数组等。 bytes("hello", "utf-8")b'hello'
complex(x) 将 x 转换为复数类型。 complex(2)(2+0j)
chr(x) 将整数 x 转换为对应的字符,x 是 Unicode 码点。 chr(97)'a'
ord(x) 将字符 x 转换为对应的整数,x 是一个单一字符。 ord('a')97
eval(x) 将字符串 x 作为 Python 表达式进行求值并返回结果。 eval('3 + 4')7
set(x) 将可迭代对象 x 转换为集合。 set([1, 2, 2, 3]){1, 2, 3}

注意事项:

  • 并不是所有类型都可以直接转换。如:

int("hello")  
# 会抛出 ValueError: invalid literal for int() with base 10: 'hello'
  • 类型转换可能会引发错误或丢失信息,比如浮点数转换为整数时,小数部分会丢失。

你可能感兴趣的:(python,开发语言)