Python 编程/数据类型
数据类型决定一个对象是否可以执行某些操作,或者是否没有意义。其他编程语言通常通过确保对象永远不会存储在将对其执行操作的位置来确定操作对对象是否有意义(这种 类型系统 称为静态类型)。Python 不会这样做。相反,它将对象的类型与对象一起存储,并在执行操作时检查该操作对该对象是否有意义(这称为动态类型)。
Python 的内置(或标准)数据类型可以分成几个类别。遵循官方 Python 文档中使用的层次结构方案,它们是 **数值类型、序列、集合和映射**(以及此处未进一步讨论的其他一些类型)。如以下所述,某些类型仅在语言的某些版本中可用。
- 布尔值:内置值
True
和False
的类型。在条件表达式中以及您想要表示某个条件的真假性时很有用。通常可以与整数 1 和 0 互换。事实上,条件表达式将接受任何类型的值,将特殊值(如布尔值False
、整数 0 和空字符串""
)视为等同于False
,并将所有其他值视为等同于True
。
数值类型
- int:整数;在 Python 2.x 中等效于 C 中的 longs,在 Python 3.x 中长度不受限制
- long:长度不受限制的长整数;仅存在于 Python 2.x 中
- float:浮点数,等效于 C 中的 doubles
- complex:复数
序列
- str:字符串;在 Python 2.x 中表示为 8 位字符的序列,但在 Python 3.x 中表示为 Unicode 字符的序列(在 U+0000 - U+10FFFF 范围内)
- bytes:0-255 范围内的整数序列;仅在 Python 3.x 中可用
- 字节数组:与字节类似,但可变(见下文);仅在 Python 3.x 中可用
- 列表
- 元组
集合
- set:唯一对象的无序集合;从 Python 2.6 开始作为标准类型可用
- frozenset:与 set 类似,但不可变(见下文);从 Python 2.6 开始作为标准类型可用
映射
- dict:Python 字典,也称为哈希表或关联数组,这意味着列表中的一个元素与一个定义相关联,类似于 Java 中的 Map
其他一些类型,例如类型和可调用对象
一般来说,Python 中的数据类型可以根据该类型对象的可变性或不可变性来区分。不可变类型对象的內容在创建后无法更改。
一些不可变类型 | 一些可变类型 |
---|---|
|
|
只有可变对象支持原地更改对象的方法,例如重新分配序列切片,这将适用于列表,但会对元组和字符串引发错误。
重要的是要了解,Python 中的变量实际上只是对内存中对象的引用。如果您将一个对象分配给一个变量,如下所示,
a = 1
s = 'abc'
l = ['a string', 456, ('a', 'tuple', 'inside', 'a', 'list')]
您真正做的只是让这个变量(a, s,或者l)指向该对象(1, 'abc', ['a string', 456, ('a', 'tuple', 'inside', 'a', 'list')]),它被保存在内存中的某个位置,作为访问它的便捷方法。如果您重新分配一个变量,如下所示
a = 7
s = 'xyz'
l = ['a simpler list', 99, 10]
您将使该变量指向一个不同的对象(在我们示例中是新创建的对象)。如上所述,只有可变对象可以在原地更改(l[0] = 1在我们的示例中没问题,但是s[0] = 'a'会引发错误)。当操作没有明确要求原地更改时,这会变得很棘手,例如对于+=(增量)运算符而言。当它用于不可变对象时(如在a += 1或在s += 'qwertz'中),Python 将默默地创建一个新对象,并将该变量指向它。但是,当它用于可变对象时(如在l += [1,2,3]中),该变量指向的对象将被原地更改。虽然在大多数情况下,您不必了解这种不同的行为,但当多个变量指向同一个对象时,它与相关性。在我们的示例中,假设您设置p = s和m = l,然后s += 'etc'和l += [9,8,7]。这将改变s并保留p不受影响,但会改变两者m和l因为它们都指向同一个列表对象。Python 的内置id()函数,它返回给定变量名的唯一对象标识符,可用于跟踪幕后发生的事情。
通常,Python 的这种行为会导致函数中的混乱。作为说明,请考虑以下代码
def append_to_sequence (myseq):
myseq += (9,9,9)
return myseq
tuple1 = (1,2,3) # tuples are immutable
list1 = [1,2,3] # lists are mutable
tuple2 = append_to_sequence(tuple1)
list2 = append_to_sequence(list1)
print('tuple1 = ', tuple1) # outputs (1, 2, 3)
print('tuple2 = ', tuple2) # outputs (1, 2, 3, 9, 9, 9)
print('list1 = ', list1) # outputs [1, 2, 3, 9, 9, 9]
print('list2 = ', list2) # outputs [1, 2, 3, 9, 9, 9]
这将产生上述指示的(通常是意外的)输出。myseq是append_to_sequence函数的局部变量,但当该函数被调用时,myseq仍然将指向与我们传入的变量(t或l在我们示例中)相同的对象。如果该对象是不可变的(例如元组),则不会有任何问题。+= 运算符将导致创建一个新的元组,并且myseq将被设置为指向它。但是,如果我们传入一个对可变对象的引用,则该对象将被原地操作(因此myseq和l在我们的示例中,最终将指向同一个列表对象)。
链接
- 3.1. 对象、值和类型,Python 语言参考,docs.python.org
- 5.6.4. 可变序列类型,Python 标准库,docs.python.org
文字整数可以通过三种方式输入
- 十进制数可以直接输入
- 十六进制数可以通过在前面添加 0x 或 0X 来输入(0xff 是十六进制 FF,或十进制 255)
- 八进制文字的格式取决于 Python 的版本
- Python 2.x:可以通过在前面添加零 (0) 来输入八进制数 (0732 是八进制 732,或十进制 474)
- Python 3.x:可以通过在前面添加零,后跟字母 O (0o 或 0O) 来输入八进制数 (0o732 是八进制 732,或十进制 474)
浮点数可以直接输入。
长整数可以通过直接输入 (1234567891011121314151617181920 是一个长整数) 或通过在后面添加 L (0L 是一个长整数) 来输入。涉及短整数溢出的计算会自动转换为长整数。
复数可以通过添加一个实数和一个虚数来输入,虚数可以通过在后面添加 j 来输入(例如 10+5j 是一个复数。10j 也是一个复数)。请注意,单独的 j 不构成一个数字。如果需要,请使用 1j。
字符串可以是单引号或三引号字符串。区别在于开始和结束分隔符,以及单引号字符串不能跨越多行。单引号字符串可以通过输入单引号 (') 或双引号 (") 后面跟着其匹配项来输入。因此
'foo' works, and "moo" works as well, but 'bar" does not work, and "baz' does not work either. "quux'' is right out.
三引号字符串类似于单引号字符串,但可以跨越多行。它们的开始和结束分隔符也必须匹配。它们用三个连续的单引号或双引号输入,因此
'''foo''' works, and """moo""" works as well, but '"'bar'"' does not work, and """baz''' does not work either. '"'quux"'" is right out.
元组在括号中输入,条目之间用逗号隔开
(10, 'Mary had a little lamb')
此外,当不含糊时,可以省略括号
10, 'whose fleece was as white as snow'
请注意,单元素元组可以通过将条目用括号括起来并添加逗号来输入,例如
('this is a singleton tuple',)
列表类似,但用方括号
['abc', 1,2,3]
字典通过用花括号将用冒号分隔的键/值对列表括起来,并用逗号将其他条目分隔开来,来创建
{ 'hello': 'world', 'weight': 'African or European?' }
这些复合类型中的任何一个都可以包含任何其他类型,深度不受限制
((((((((('bob',),['Mary', 'had', 'a', 'little', 'lamb']), { 'hello' : 'world' } ),),),),),),)
在 Python 中,类似于其他编程语言中的空指针,使用 None 来表示。None 不是空指针或空引用,而是一个实际存在的对象,并且只有一个实例。None 的用途之一是在函数的默认参数值中,详情请参见 Python Programming/Functions#Default_Argument_Values。通常使用 is 而不是 == 来比较 None。
测试 None 和赋值
if item is None:
...
another = None
if not item is None:
...
if item is not None: # Also possible
...
在默认参数值中使用 None
def log(message, type = None):
...
PEP8 规定“与单例(如 None)的比较应该始终使用 is 或 is not,而不是相等运算符”。因此,“if item == None:” 是不可取的。类可以重新定义相等运算符(==),以便该类的实例等于 None。
你可以通过 dir(None) 或 id(None) 来验证 None 是一个对象。
另请参见 Operators#Identity 章节。
链接
- 4. 内置常量,docs.python.org
- 3.11.7 空对象,docs.python.org
- Python None 比较:我应该使用 “is” 还是 ==?,stackoverflow.com
- PEP 0008 -- Python 代码风格指南,python.org
类型转换
[edit | edit source]Python 中类型转换示例
v1 = int(2.7) # 2
v2 = int(-3.9) # -3
v3 = int("2") # 2
v4 = int("11", 16) # 17, base 16
v5 = long(2) # Python 2.x only, not Python 3.x
v6 = float(2) # 2.0
v7 = float("2.7") # 2.7
v8 = float("2.7E-2") # 0.027
v9 = float(False) # 0.0
vA = float(True) # 1.0
vB = str(4.5) # "4.5"
vC = str([1, 3, 5]) # "[1, 3, 5]"
vD = bool(0) # False; bool fn since Python 2.2.1
vE = bool(3) # True
vF = bool([]) # False - empty list
vG = bool([False]) # True - non-empty list
vH = bool({}) # False - empty dict; same for empty tuple
vI = bool("") # False - empty string
vJ = bool(" ") # True - non-empty string
vK = bool(None) # False
vL = bool(len) # True
vM = set([1, 2])
vN = set((1, 2)) # Converts any sequence, not just a list
vO = set("abc") # {'c', 'b', 'a'}
vP = set(b"abc") # {97, 98, 99}
vQ = list(vM)
vR = list({1: "a", 2: "b"}) # dict -> list of keys
vS = tuple(vQ)
vT = list("abc") # ['a', 'b', 'c']
print(v1, v2, v3, type(v1), type(v2), type(v3))
隐式类型转换
int1 = 4
float1 = int1 + 2.1 # 4 converted to float
# str1 = "My int:" + int1 # Error: no implicit type conversion from int to string
str1 = "My int:" + str(int1)
int2 = 4 + True # 5: bool is implicitly converted to int
float2 = 4.5 + True # 5.5: True is converted to 1, which is converted to 1.0
关键词:类型强制转换。
链接
- 2. 内置函数 # bool,docs.python.org
- 2. 内置函数 # list,docs.python.org
- 2. 内置函数 # float,docs.python.org
- 2. 内置函数 # int,docs.python.org
- 2. 内置函数 # set,docs.python.org
- 2. 内置函数 # str,docs.python.org
- 2. 内置函数 # type,docs.python.org
- 2. 内置函数 # tuple,docs.python.org
练习
[edit | edit source]- 编写一个程序,实例化一个对象,将 [1,2] 添加到该对象中,并返回结果。
- 找到一个对象,它返回相同长度的输出(如果存在的话?)。
- 找到一个对象,它返回的输出长度比初始长度大 2。
- 找到一个导致错误的对象。
- 找到两种数据类型 X 和 Y,使得 X = X + Y 会导致错误,但 X += Y 不会。