Skip to content

赋值拷贝、空、数据类型

更新: 2025/2/24 字数: 0 字 时长: 0 分钟

赋值拷贝

赋值

赋值,之前讲过就是将一个变量名和一个对象进行绑定,这样变量就成为了该对象的一个引用,同时在此过程中增加了对象的引用次数。

python
alist = [1,2,3,["a","b"]]  # 注释:[1,2,3,["a","b"]]是可变列表对象,变量alist是该对象的一个引用。
b = alist                  # 注释:变量alist将可变列表对象的引用赋值给变量b。
alist.append(5)            # 注释:变量alist引用可变列表对象增添元素。
b.append(6)                # 注释:变量b引用了同一个可变列表对象增添元素。
print(alist)               # 输出:[1, 2, 3, ['a', 'b'], 5, 6]
print(b)                   # 输出:[1, 2, 3, ['a', 'b'], 5, 6]。注释:变量alist、变量b引用的都是同一个对象,因此这里的输出和上面的输出相同。

546188-20181031094701785-1018065288

如果将一个可变对象赋值给多个变量时,那么这些变量引用的是同一个对象。如果一个变量修改了引用对象的内容,那么所有引用这个对象的变量都会看到这个变化,因为它们指向的是同一个对象。

python
a = [[0] for _ in range(3)]  # 注释:变量a为[[0], [0], [0]]的一个引用,里面的[0]是独立对象
print('a: ', a)              # 输出:a:  [[0], [0], [0]]
a[0][0] = 1
print('a: ', a)              # 输出:a:  [[1], [0], [0]]

item = [0]                   # 注释:变量item为[0]的一个引用,下面用到item都是[0]这一个对象
b = [item for _ in range(3)]
print('b: ', b)              # 输出:b:  [[0], [0], [0]]
b[0][0] = 1
print('b: ', b)              # 输出:b:  [[1], [1], [1]]

image-20240407113847068

浅拷贝

浅拷贝(不完全拷贝):当拷贝可变对象时,若对象是单层结构,拷贝其对象会生成新的独立对象,若对象是多层结构,最外层结构拷贝形成新的结构,内层结构就拷贝其引用,形成新的对象,新对象和原对象的关系就像是连体婴儿,有相互独立的部分,又有相互共享的部分。当拷贝不可变对象时,只会拷贝其引用,不会有新的对象产生。

python
# 引入copy模块
import copy

alist = [1, 2, 3, ["a", "b"]]  # 注释:[1,2,3,["a","b"]]是可变列表对象,变量alist是该对象的一个引用。
c = copy.copy(alist)           # 注释:浅拷贝对最外层列表[1,2,3]进行了拷贝形成了新的列表,对内层列表["a","b"]的引用进行了拷贝,最终形成新的对象,变量c再成为该新对象的引用。
alist.append(5)                # 注释:变量alist引用了可变列表对象中的外层列表[1,2,3]添加了元素,由于[1,2,3]是独立的列表,因此该操作只会影响变量alist引用对象里面的外层列表。
alist[3].append('cccc')        # 注释:变量alist引用了可变列表对象中的内层列表["a","b"]添加了元素,由于浅拷贝所拷贝的是["a","b"]的引用,因此内层列表["a","b"]是变量alist、变量c共同引用的列表,所以该操作会影响变量alist、变量c引用对象里面的内层列表。
print(alist)                   # 输出:[1, 2, 3, ['a', 'b', 'cccc'], 5]
print(c)                       # 输出:[1, 2, 3, ['a', 'b', 'cccc']]

546188-20181031095328930-1590606034

深拷贝

深拷贝(完全拷贝):当拷贝可变对象时,会拷贝出一个与原对象完全一样的对象放到新的内存地址中成为新的对象,新对象和原对象之间相互独立。当拷贝不可变对象时,只会拷贝其引用,不会有新的对象产生。

python
# 引入copy模块
import copy

alist=[1, 2, 3,["a", "b"]]  # 注释:[1,2,3,["a","b"]]是可变列表对象,变量alist是该对象的一个引用。
d=copy.deepcopy(alist)      # 注释:深拷贝将变量alist引用的可变列表对象拷贝为了一个新的独立对象,变量d再成为该新对象的引用。
alist.append(5)             # 注释:变量alist引用了可变列表对象中的外层列表[1,2,3]添加了元素,由于是独立的可变列表对象,因此该操作只会影响变量alist引用的对象。
alist[3].append("ccccc")    # 注释:变量alist引用了可变列表对象中的内层列表["a","b"]添加了元素,由于是独立的可变列表对象,因此该操作只会影响变量alist引用的对象。
print(alist)                # 输出:[1, 2, 3, ['a', 'b', 'ccccc'], 5]
print(d)                    # 输出:[1, 2, 3, ['a', 'b']]

546188-20181031095505004-75839266

前面我们学习了 Python 常见的八种数据类型,区分这些数据类型都是基于数据存在的情况下,那么数据不存在的情况我们该如何表示呢?答案就是:空(None,首字母必须大写),它是 Python 中的一个特殊的常量类型 NoneType,它即不表示 0,也不表示空字符串、空列表、空字典、空集合、空元组,而表示没有值,也就是空值。

python
from collections.abc import Iterable

print(type(None))                    # 输出:<class 'NoneType'>
print(None is 0, None == 0)          # 输出:False False
print(None is 0.0, None == 0.0)      # 输出:False False
print(None is '', None == '')        # 输出:False False
print(None is False, None == False)  # 输出:False False
print(None is [], None == [])        # 输出:False False
print(None is {}, None == {})        # 输出:False False
print(None is set(), None == set())  # 输出:False False
print(None is (), None == ())        # 输出:False False
print(None is None, None == None)    # 输出:True True
print(isinstance(None, Iterable))    # 输出:False。注释:None不是可迭代对象。
print(hash(None))                    # 输出:85424083。注释:None是可哈希的。

重要

NoneNoneType 数据类型的唯一值(其他编程语言可能称这个值为 nullnilundefined),我们不能再创建其它 NoneType 类型的对象,但是可以将 None 赋值给任何变量。

数据类型

类型检查

前面我们使用了两种查看和判断数据类型的方法,这里详细介绍一下:

  • 查看数据类型:通过内置的 type(值) 方法获取值的数据类型。

  • 判断数据类型:通过内置的 isinstance(值,类型) 方法判断值是否是指定类型,是指定类型结果为 True,不是指定类型结果为 False

虽然你可以使用 type() 函数或 isinstance() 函数来判断数据类型,但它们用途略有不同:

  • 使用 type(值) == 指定类型 方法:通过 type() 函数来获取值的数据类型,然后将其与指定的数据类型进行比较。
python
value = 42
if type(value) == int:
    print("值是整数")  # 输出:值是整数
  • 使用 isinstance(值, 类型)isinstance(值, (类型1, 类型2...)) 方法:通过 isinstance() 函数来检查值是否属于指定的类型或类型元组。在处理多个类型时更具灵活性,通常更推荐使用 isinstance() 方法。
python
value = 3.14
if isinstance(value, float):
    print("值是浮点数")       # 输出:值是浮点数
if isinstance(value, (int, float)):
    print("值是整数或浮点数")  # 输出:值是整数或浮点数

类型特点

针对我们学习的 Python 常用的数据类型进行总结,具体参看下表:

类型关键字下标索引迭代性可变性哈希性特点
整数类型int无序不可迭代对象不可变对象可哈希只有整数
浮点型float无序不可迭代对象不可变对象可哈希存在小数
字符型str有序可迭代对象不可变对象可哈希所有字符
布尔型bool无序不可迭代对象不可变对象可哈希TrueFlase
列表list有序可迭代对象可变对象不可哈希操作自由度高
字典dict无序可迭代对象可变对象不可哈希键值对存储
集合set无序可迭代对象可变对象不可哈希自动去重
元祖tuple有序可迭代对象不可变对象可哈希(元素可哈希)内容不可改变
None无序不可迭代对象不可变对象可哈希只有None

建议

这个“哈希性”现在不理解没关系,后面会学习到,现在只需记住,不可变对象是可哈希的,而可变对象是不可哈希的。

类型转换

Python 提供了一系列将变量或值进行类型转换的内置函数,将要转换的数据添加到函数中进行转换。常用内置函数如下:

  • int() 函数:将对象类型转换成整数类型。
python
print(int(12.0))      # 输出:12。注释:浮点型转整数类型,只保留整数部分。
print(int('12.0'))    # 报错:字符串类型的浮点数字为无效文字。
print(int('12'))      # 输出:12。注释:将字符串的整数变为十进制整数类型。
print(int('+12'))     # 输出:12。注释:将字符串的整数变为十进制整数类型。
print(int('-12'))     # 输出:-12。注释:将字符串的整数变为十进制整数类型。
print(int('10', 2))   # 输出:2。注释:将二进制字符串变为十进制整数类型。
print(int('10', 8))   # 输出:8。注释:将八进制字符串变为十进制整数类型。
print(int('10', 16))  # 输出:16。注释:将十六进制字符串变为十进制整数类型。
print(int(False))     # 输出:0。注释:布尔型转整数类型,True = 1、False = 0。
print(int(True))      # 输出:1。注释:布尔型转整数类型,True = 1、False = 0。
print(int('a'))       # 报错:a不是数字。注释:字符串只能包含0~9数字才能被转换成整数类型,可先用isdigit方法检测。
print(int([12]))      # 报错:列表不能转换为整数类型。
print(int({'1': 2}))  # 报错:字典不能转换为整数类型。
print(int({1, 2}))    # 报错:集合不能转换为整数类型。
print(int((1, 2)))    # 报错:元组不能转换为整数类型。
print(int(None))      # 报错:None不能转换为整数类型。
  • float() 函数:将对象类型转换成浮点型。
python
print(float(123))       # 输出:123.0。注释:整数类型转浮点型,在整数后面加一个.0。
print(float(False))     # 输出:0.0。注释:布尔型转浮点型,True = 1.0、False = 0.0。
print(float(True))      # 输出:1.0。注释:布尔型转浮点型,True = 1.0、False = 0.0。
print(float('100.23'))  # 输出:100.23
print(float('-100'))    # 输出:-100
print(float('+100'))    # 输出:100
print(float('a'))       # 错误,a不是数字。注释:字符串只能包含0~9数字和.小数点才能被转换成浮点型。
print(float([12]))      # 报错:列表不能转换为浮点型。
print(float({'1': 2}))  # 报错:字典不能转换为浮点型。
print(float({1, 2}))    # 报错:集合不能转换为浮点型。
print(float((1, 2)))    # 报错:元组不能转换为浮点型。
print(float(None))      # 报错:None不能转换为浮点型。
  • str() 函数:将对象类型转换成字符型。任何类型的数据都可以转换成字符串,其实就是直接在数据的外层加引号转为字符串类型。
python
print(str(2))         # 输出:'2'
print(str(2.0))       # 输出:'2.0'
print(str(True))      # 输出:'True'
print(str([12]))      # 输出:'[12]'
print(str({'1': 2}))  # 输出:"{'1': 2}"
print(str({1, 2}))    # 输出:'{1, 2}'
print(str((1, 2)))    # 输出:'(1, 2)'
print(str(None))      # 输出:'None'
  • bool() 函数:将对象类型转换成布尔值。任何类型的数据均可以转换成布尔值,其中 00.0None、空字符串、空列表、空字典、空集合、空元组的布尔值都为 False,其它数据的布尔值都为 True
python
print(bool(1))         # 输出:True
print(bool(0))         # 输出:False
print(bool(-1))        # 输出:True
print(bool(1.0))       # 输出:True
print(bool(0.0))       # 输出:False
print(bool(-1.0))      # 输出:True
print(bool(''))        # 输出:False
print(bool('cz'))      # 输出:True
print(bool([]))        # 输出:False
print(bool([12]))      # 输出:True
print(bool({}))        # 输出:False
print(bool({'1': 2}))  # 输出:True
print(bool(set()))     # 输出:False
print(bool({1, 2}))    # 输出:True
print(bool(()))        # 输出:False
print(bool((1, 2)))    # 输出:True
print(bool(None))      # 输出:False
  • list() 函数:将可迭代对象拆分然后合并成列表类型数据。
python
print(list(0))         # 报错:0是整数类型,不是可迭代对象。
print(list(0.0))       # 报错:0.0是浮点型,不是可迭代对象。
print(list('01'))      # 输出:['0', '1']
print(list(True))      # 报错:True是布尔型,不是可迭代对象。
print(list({'1': 0}))  # 输出:['1']。注释:字典转列表,只会保留键的数据。
print(list({'1', 0}))  # 输出:[0, '1']
print(list(('1', 0)))  # 输出:['1', 0]
print(list(range(5)))  # 输出:[0, 1, 2, 3, 4]
print(list(None))      # 报错:None不是可迭代对象。
  • dict() 函数:将可迭代对象转换成字典类型。
python
print(dict(1))                 # 报错:1是整数类型,不是可迭代对象。
print(dict(1.0))               # 报错:1.0是浮点型,不是可迭代对象。
print(dict('1.0'))             # 报错:字典更新序列元素错误。
print(dict(True))              # 报错:True是布尔型,不是可迭代对象。
print(dict([1, 2]))            # 报错:字典更新序列元素错误。
print(dict([[1, 2]]))          # 输出:{1: 2}。注释:不建议这样写。
print(dict([{1, 2}]))          # 输出:{1: 2}。注释:不建议这样写。
print(dict([(1, 2)]))          # 输出:{1: 2}
print(dict(([1, 2], [3, 4])))  # 输出:{1: 2, 3: 4}。注释:不建议这样写。
print(dict([(1, 2), (3, 4)]))  # 输出:{1: 2, 3: 4}
print(dict(((1, 2), (3, 4))))  # 输出:{1: 2, 3: 4}
print(dict(None))              # 报错:None不是可迭代对象。
  • set() 函数:将可迭代对象拆分然后合并成集合类型数据。
python
print(set(0))         # 报错:0是整数类型,不是可迭代对象。
print(set(0.0))       # 报错:0.0是浮点型,不是可迭代对象。
print(set('01'))      # 输出:{'0', '1'}
print(set(True))      # 报错:True是布尔型,不是可迭代对象。
print(set(['1', 0]))  # 输出:{0, '1'}
print(set({'1': 0}))  # 输出:{'1'}。注释:字典转集合,只会保留键的数据。
print(set(('1', 0)))  # 输出:{0, '1'}
print(set(range(5)))  # 输出:{0, 1, 2, 3, 4}
print(set(None))      # 报错:None不是可迭代对象。
  • tuple() 函数:将可迭代对象拆分然后合并成元组类型数据。
python
print(tuple(0))         # 报错:0是整数类型,不是可迭代对象。
print(tuple(0.0))       # 报错:0.0是浮点型,不是可迭代对象。
print(tuple('01'))      # 输出:('0', '1')
print(tuple(True))      # 报错:True是布尔型,不是可迭代对象。
print(tuple(['1', 0]))  # 输出:('1', 0)
print(tuple({'1': 0}))  # 输出:('1',)。注释:字典转元组,只会保留键的数据。
print(tuple({'1', 0}))  # 输出:(0, '1')
print(tuple(range(5)))  # 输出:(0, 1, 2, 3, 4)
print(tuple(None))      # 报错:None不是可迭代对象。
  • eval('字符串')函数:执行字符串类型数据的表达式并返回表达式的值。
python
a = '2'
b = eval(a)
print(b, type(b))  # 输出:2 <class 'int'>

a = '2 + 2'
b = eval(a)
print(b, type(b))  # 输出:4 <class 'int'>

a = '2.01'
b = eval(a)
print(b, type(b))  # 输出:2.01 <class 'float'>

a = '2.01 + 3.85'
b = eval(a)
print(b, type(b))  # 输出:5.859999999999999 <class 'float'>

a = '"2"'
b = eval(a)
print(b, type(b))  # 输出:2 <class 'str'>

a = '"2" * 3'
b = eval(a)
print(b, type(b))  # 输出:222 <class 'str'>

a = 'True'
b = eval(a)
print(b, type(b))  # 输出:True <class 'bool'>

a = 'True + False'
b = eval(a)
print(b, type(b))  # 输出:1 <class 'int'>

a = '[1, 2, 3]'
b = eval(a)
print(b, type(b))  # 输出:[1, 2, 3] <class 'list'>

a = "{'a': 1, 'b': 2}"
b = eval(b)
print(b, type(b))  # 输出:{'a': 1, 'b': 2} <class 'dict'>

a = '{1, 2, 3}'
b = eval(a)
print(b, type(b))  # 输出:{1, 2, 3} <class 'set'>

a = '(1, 2, 3)'
b = eval(a)
print(b, type(b))  # 输出:(1, 2, 3) <class 'tuple'>