Python(考试基础)- 数据类型

675 阅读32分钟

1. 空值

在 Python 中,空值(Null)通常表示“无值”或“未定义的值”。Python 使用 None 来表示空值。

变量初始化

a = None
print(a)  # 输出: None

判断是否为空

判断一个变量是否为 None,推荐使用 is 运算符,而不是 ==,因为 is 会检查对象的身份。

a = None
if a is None:
    print("a is None")  # 输出: a is None

print(a == 0)   # 输出: False
print(a == '')  # 输出: False
print(a == False)  # 输出: False
print(a == None)  # 输出: True

函数返回空值

如果函数没有明确的返回语句,Python 会自动返回 None

def foo():
    pass  # 没有返回值

result = foo()
print(result)  # 输出: None

默认参数值

def greet(name=None):
    if name is None:
        name = 'Guest'
    print(f"Hello, {name}!")

greet()  # 输出: Hello, Guest!
greet('Alice')  # 输出: Hello, Alice!

2. 布尔

在 Python 中,布尔类型 (bool) 是一种表示真或假的数据类型。布尔类型只有两个可能的值:

  • True:表示真。
  • False:表示假。
# 定义布尔变量
a = True
b = False

print(a)  # 输出: True
print(b)  # 输出: False

真假值

会被视为假值的内置对象:

  • 被定义为假值的常量: None  和  False
  • 任何数值类型的零: 00.00jDecimal(0)Fraction(0, 1)
  • 空的序列和多项集: ''()[]{}set()range(0)
# 假值常量
print(bool(None))   # False
print(bool(False))  # False

# 数值类型的零
print(bool(0))      # False
print(bool(0.0))    # False
print(bool(0j))     # False
from decimal import Decimal
print(bool(Decimal(0)))  # False
from fractions import Fraction
print(bool(Fraction(0, 1)))  # False

# 空的序列和多项集
print(bool(''))         # False,空字符串
print(bool(()))         # False,空元组
print(bool([]))         # False,空列表
print(bool({}))         # False,空字典
print(bool(set()))      # False,空集合
print(bool(range(0)))   # False,空 range

运算符

Python 提供了以下布尔运算符来执行逻辑运算:

  • and:与运算,只有两个条件都为真时,结果才为真。
  • or:或运算,只有两个条件都为假时,结果才为假。
  • not:非运算,取反。
# 逻辑运算
a = True
b = False

print(a and b)  # 输出: False,两个条件都为真时结果才为真
print(a or b)   # 输出: True,两个条件中有一个为真,结果为真
print(not a)    # 输出: False,取反

条件判断

布尔类型常用于控制流程结构,如 if 语句:

if a:
    print("a 是 True")
else:
    print("a 是 False")

3. 数字

整数

整数可以是正整数、负整数或零,且没有小数部分。

a = 10      # 正整数
b = -5      # 负整数
c = 0       # 零

在 Python 中,int 类型的整数是没有大小限制的,直到你的机器内存不足为止。Python 会自动调整整数的大小。

large_int = 1234567890123456789012345678901234567890
print(large_int)  # 输出一个非常大的整数

进制

进制表示

Python 支持不同进制的整数表示:

  • 十进制(默认):普通的数字表示。
  • 二进制:使用 0b0B 开头。
  • 八进制:使用 0o0O 开头。
  • 十六进制:使用 0x0X 开头。
# 十进制
decimal = 42

# 二进制
binary = 0b101010  # 42

# 八进制
octal = 0o52      # 42

# 十六进制
hexadecimal = 0x2A  # 42

print(decimal, binary, octal, hexadecimal)  # 42 42 42 42
进制转换

从十进制转换为其他进制

Python 提供了内置函数来将十进制整数转换为二进制、八进制和十六进制。

  • bin() :将整数转换为二进制表示(返回字符串)。
  • oct() :将整数转换为八进制表示(返回字符串)。
  • hex() :将整数转换为十六进制表示(返回字符串)。
# 十进制数
decimal = 42

# 转换为二进制
binary = bin(decimal)  # '0b101010'
print(binary)

# 转换为八进制
octal = oct(decimal)   # '0o52'
print(octal)

# 转换为十六进制
hexadecimal = hex(decimal)  # '0x2a'
print(hexadecimal)

说明

  • bin()oct()hex() 都会返回带有前缀的字符串(分别是 0b0o0x),表示该数字的进制。

  • 若需要去掉前缀,可以使用字符串切片:

    binary = bin(decimal)[2:]  # '101010'
    octal = oct(decimal)[2:]   # '52'
    hexadecimal = hex(decimal)[2:]  # '2a'
    
  1. 从其他进制转换为十进制

可以使用 Python 的 int() 函数将一个特定进制的字符串转换为十进制整数。int() 函数需要指定数字字符串的进制。

  • int(string, base) :将指定进制的数字字符串转换为十进制整数,base 是数字字符串的进制。
# 二进制转十进制
binary_str = '101010'
decimal_from_binary = int(binary_str, 2)
print(decimal_from_binary)  # 42

# 八进制转十进制
octal_str = '52'
decimal_from_octal = int(octal_str, 8)
print(decimal_from_octal)  # 42

# 十六进制转十进制
hexadecimal_str = '2a'
decimal_from_hexadecimal = int(hexadecimal_str, 16)
print(decimal_from_hexadecimal)  # 42
  1. 其他进制的转换

你也可以进行进制之间的直接转换,先转换为十进制,再转换为目标进制。例如,二进制转十六进制:

# 二进制转十进制
binary_str = '101010'
decimal = int(binary_str, 2)

# 十进制转十六进制
hexadecimal = hex(decimal)[2:]  # '2a'
print(hexadecimal)  # 2a

浮点数

在 Python 中,浮点数(float)是表示带有小数点的数字的类型。浮点数可以用于表示实数(有小数部分的数字),并支持各种算术运算、比较和转换。

表示

浮点数可以是正数、负数或零,且包含小数部分。浮点数也可以通过科学计数法(eE)表示。

# 普通浮点数
a = 3.14
b = -2.5
c = 0.0

# 科学计数法表示
d = 1.23e4  # 1.23 × 10^4 = 12300.0
e = 5E-3    # 5 × 10^-3 = 0.005

精度问题

浮点数在计算机中使用有限的位数表示,因此在表示一些十进制数时,可能会发生精度丢失。比如:

a = 0.1 + 0.2
print(a)  # 0.30000000000000004

这种现象是浮点数表示精度有限造成的。在实际使用中,通常会将浮点数四舍五入到所需的位数。

由于浮点数的精度问题,直接比较两个浮点数是否相等可能会出现问题。为了避免这种情况,通常使用 math.isclose() 函数来比较两个浮点数是否相等,允许一定的误差范围。

import math

a = 0.1 + 0.2
b = 0.3

# 使用 isclose 来比较浮点数
print(math.isclose(a, b))  # True

常见方法

  • round() :四舍五入到指定小数位数。

    value = 3.14159
    rounded_value = round(value, 2)  # 保留两位小数
    print(rounded_value)  # 3.14
    
  • float() :将其他类型(如整数、字符串)转换为浮点数。

    integer_value = 10
    float_value = float(integer_value)  # 转换为浮点数
    print(float_value)  # 10.0
    
    str_value = "12.34"
    float_value = float(str_value)  # 转换为浮点数
    print(float_value)  # 12.34
    
  • isnan() :检查浮点数是否是 NaN(不是一个数字)。

    import math
    nan_value = math.nan
    print(math.isnan(nan_value))  # True
    
  • inf-inf:浮点数的正无穷大和负无穷大。

    positive_infinity = float('inf')
    negative_infinity = float('-inf')
    print(positive_infinity > 10000)  # True
    print(negative_infinity < -10000)  # True
    

复数

在 Python 中,复数(complex)是一种表示复数的类型。复数由实部和虚部组成,虚部以 j 结尾。

创建

a = 1 + 2j
b = complex(1, 2)

访问实部和虚部

a = 1 + 2j
print(a.real)  # 输出: 1.0
print(a.imag)  # 输出: 2.0

常见方法

  • conjugate() :返回复数的共轭复数。
a = 1 + 2j
print(a.conjugate())  # 输出: (1-2j)

4. 字符串

创建

以下常见的字符串创建方式:

1. 使用单引号 (') 或双引号 (")

str1 = 'Hello'
str2 = "World"
  • 单引号和双引号功能一样,可以根据需求选择。

2. 使用三引号('''"""

三引号可以用于创建多行字符串或包含换行符的字符串。

str3 = '''Hello
World'''
str4 = """This is
a multi-line string"""
  • 使用三引号时,字符串可以跨越多行,并且可以保留换行符。

3. 使用 str() 函数

str5 = str(123)
  • str() 函数用于将其他数据类型转换为字符串,通常用于将数字、列表等转换为字符串。

4. 使用 join() 方法

str6 = ''.join(['H', 'e', 'l', 'l', 'o'])
  • join() 是字符串对象的方法,常用于将序列中的元素连接成一个字符串。

字符串格式化

在 Python 中,除了使用 formatformat_map 进行字符串格式化外,还可以使用其他几种方式来进行字符串格式化。以下是常见的几种字符串格式化方法的总结:

  1. 百分号 (%) 格式化

这是 Python 2 中常用的格式化方法,在 Python 3 中依然有效。其基本语法为 "%格式化符号" % 值

name = 'Alice'
age = 25
text = 'Hello, %s! You are %d years old.' % (name, age)
print(text)  # 输出 'Hello, Alice! You are 25 years old.'
  1. f-字符串(格式化字符串字面量)

从 Python 3.6 开始,支持使用 f-字符串(formatted string literals)。它通过在字符串前加 fF,并直接在字符串中嵌入表达式进行格式化。

name = 'Alice'
age = 25
text = f'Hello, {name}! You are {age} years old.'
print(text)  # 输出 'Hello, Alice! You are 25 years old.'
  1. str.format()

str.format() 是 Python 3 中推荐的格式化方法,它比 % 格式化更强大且灵活,支持位置参数和关键字参数。

name = 'Alice'
age = 25
text = 'Hello, {}! You are {} years old.'.format(name, age)
print(text)  # 输出 'Hello, Alice! You are 25 years old.'

支持键值对:

text = 'Hello, {name}! You are {age} years old.'.format(name='Alice', age=25)
print(text)  # 输出 'Hello, Alice! You are 25 years old.'
  1. str.format_map()

format_map() 方法与 str.format() 类似,不过它通过一个字典来提供数据,替换字符串中的字段。

text = 'Hello, {name}! You are {age} years old.'
text = text.format_map({'name': 'Alice', 'age': 25})
print(text)  # 输出 'Hello, Alice! You are 25 years old.'
  1. Template 类(string.Template)

string.Template 提供了一种简化的字符串格式化方式,适用于简单的插值需求。它通过 $ 符号来表示变量。

from string import Template

# 示例
template = Template('Hello, $name! You are $age years old.')
text = template.substitute(name='Alice', age=25)
print(text)  # 输出 'Hello, Alice! You are 25 years old.'

编码与解码

在 Python 中,编码解码通常是指将字符串与字节数据之间的转换。编码是将字符串转换为字节数据(bytes),而解码是将字节数据转换为字符串。常见的应用场景包括文件读取、网络通信、加密处理等。

编码:encode()

字符串通过指定编码格式转为字节类型。常见的编码格式有 UTF-8、ASCII、GBK 等。

# 使用 UTF-8 编码字符串为字节
text = "Hello, World!"
encoded_text = text.encode('utf-8')
print(encoded_text)  # 输出: b'Hello, World!',这是字节类型(bytes)

# 使用 GBK 编码(常用于中文字符)
text = "你好"
encoded_text = text.encode('gbk')
print(encoded_text)  # 输出: b'\xc4\xe3\xba\xc3'

解码:decode()

字节数据可以通过指定编码格式解码回字符串。

# 字节数据解码为字符串
encoded_text = b'Hello, World!'
decoded_text = encoded_text.decode('utf-8')
print(decoded_text)  # 输出: Hello, World!

# 解码 GBK 编码的字节数据
encoded_text = b'\xc4\xe3\xba\xc3'
decoded_text = encoded_text.decode('gbk')
print(decoded_text)  # 输出: 你好

错误处理

在编码或解码过程中,如果遇到无法处理的字符,Python 提供了错误处理选项。常见的错误处理模式有:

  • ignore:忽略无法编码/解码的字符。
  • replace:用替代字符(如 ?)替代无法编码/解码的字符。
  • strict(默认):如果无法编码/解码,则抛出 UnicodeEncodeErrorUnicodeDecodeError
# 编码时使用 ignore 选项
text = "你好"
encoded_text = text.encode('ascii', 'ignore')  # 忽略非 ASCII 字符
print(encoded_text)  # 输出: b''(空字节)

# 解码时使用 replace 选项
encoded_text = b'Hello, \xe4\xbd\xa0\xe5\xa5\xbd'
decoded_text = encoded_text.decode('utf-8', 'replace')
print(decoded_text)  # 输出: Hello, 你?好

常见编码格式

  • UTF-8:兼容性好,支持世界上几乎所有的字符集,广泛应用于网页、API 和文件编码。
  • ASCII:仅支持英语字符。
  • GBK/GB2312:常见于中文环境中,GBK 是对 GB2312 的扩展。

Python 2 与 Python 3 的区别

  • Python 2 中,字符串默认是字节类型(str),而在 Python 3 中,字符串默认是 Unicode 类型(str),字节数据使用 bytes 类型。
  • Python 2 使用 unicode 类型处理 Unicode 字符串,需要显式地调用 encode()decode(),而 Python 3 的字符串默认为 Unicode,字节数据必须显式转换为 bytes

好的,以下是按照分类整理并附带代码示例的 Python 3.8 字符串方法:

大小写和字符转换

  • capitalize() : 将字符串的第一个字符转换为大写,其余字符转换为小写。

    text = 'hello'
    print(text.capitalize())  # 输出 'Hello'
    
  • casefold() : 返回一个新的字符串,所有字符都转换为小写,适用于语言无关的比较。

    text = 'HELLO'
    print(text.casefold())  # 输出 'hello'
    
  • lower() : 返回一个新的字符串,将所有字符转换为小写。

    text = 'HELLO'
    print(text.lower())  # 输出 'hello'
    
  • upper() : 返回一个新的字符串,将所有字符转换为大写。

    text = 'hello'
    print(text.upper())  # 输出 'HELLO'
    
  • swapcase() : 返回一个新的字符串,将所有大写字母转换为小写字母,反之亦然。

    text = 'HeLLo'
    print(text.swapcase())  # 输出 'hElLO'
    

字符串对齐

  • center(width, fillchar=' ') : 返回一个新的字符串,将原字符串居中,填充指定的字符,默认使用空格。

    text = 'hello'
    print(text.center(10, '-'))  # 输出 '--hello---'
    
  • ljust(width, fillchar=' ') : 返回一个新的字符串,将原字符串左对齐,剩余部分填充指定的字符。

    text = 'hello'
    print(text.ljust(10, '-'))  # 输出 'hello-----'
    
  • rjust(width, fillchar=' ') : 返回一个新的字符串,将原字符串右对齐,剩余部分填充指定的字符。

    text = 'hello'
    print(text.rjust(10, '-'))  # 输出 '-----hello'
    
  • zfill(width) : 返回一个新的字符串,将原字符串填充为指定宽度,前面补零。

    text = '42'
    print(text.zfill(5))  # 输出 '00042'
    
  • expandtabs(tabsize=8) : 返回一个新的字符串,将字符串中的制表符(\t)替换为指定数量的空格。

    text = 'hello\tworld'
    print(text.expandtabs(4))  # 输出 'hello   world'
    

查找与定位

  • find(substring, start=0, end=len(string)) : 返回子字符串第一次出现的索引,如果找不到返回 -1。

    text = 'hello'
    print(text.find('l'))  # 输出 2
    
  • index(substring, start=0, end=len(string)) : 类似于 find(),但如果子字符串不存在,则会抛出 ValueError

    text = 'hello'
    print(text.index('l'))  # 输出 2
    
  • rfind(substring, start=0, end=len(string)) : 返回子字符串最后一次出现的索引,找不到返回 -1。

    text = 'hello'
    print(text.rfind('l'))  # 输出 3
    
  • rindex(substring, start=0, end=len(string)) : 类似于 rfind(),但找不到时抛出 ValueError

    text = 'hello'
    print(text.rindex('l'))  # 输出 3
    
  • startswith(prefix, start=0, end=len(string)) : 判断字符串是否以指定前缀开始。

    text = 'hello'
    print(text.startswith('h'))  # 输出 True
    
  • endswith(suffix, start=0, end=len(string)) : 判断字符串是否以指定后缀结束。

    text = 'hello'
    print(text.endswith('o'))  # 输出 True
    

字符串分割与连接

  • split(separator=None, maxsplit=-1) : 将字符串分割成多个部分,返回一个列表。

    text = 'hello world'
    print(text.split())  # 输出 ['hello', 'world']
    
  • splitlines(keepends=False) : 按行分割字符串,返回一个列表。

    text = 'hello\nworld'
    print(text.splitlines())  # 输出 ['hello', 'world']
    
  • join(iterable) : 将一个可迭代对象中的元素连接为一个字符串。

    text = '-'
    print(text.join(['a', 'b', 'c']))  # 输出 'a-b-c'
    
  • partition(separator) : 将字符串分成三个部分:分隔符之前、分隔符、分隔符之后。

    text = 'hello world'
    print(text.partition(' '))  # 输出 ('hello', ' ', 'world')
    

去除空白字符

  • strip(chars=None) : 返回一个新的字符串,去除字符串两端的空白或指定字符。

    text = '  hello  '
    print(text.strip())  # 输出 'hello'
    
  • lstrip(chars=None) : 返回一个新的字符串,去除字符串左侧的空白或指定字符。

    text = '  hello  '
    print(text.lstrip())  # 输出 'hello  '
    
  • rstrip(chars=None) : 返回一个新的字符串,去除字符串右侧的空白或指定字符。

    text = '  hello  '
    print(text.rstrip())  # 输出 '  hello'
    

字符串替换

  • replace(old, new, count=-1) : 替换字符串中的指定子字符串。

    text = 'hello'
    print(text.replace('e', 'a'))  # 输出 'hallo'
    
  • translate(table) : 根据字符映射表对字符串进行转换。

    table = str.maketrans('h', 'j')
    text = 'hello'
    print(text.translate(table))  # 输出 'jello'
    
  • maketrans(x, y) : 返回一个字符映射表,可以用于 translate() 方法。

    table = str.maketrans('abc', '123')
    text = 'abc'
    print(text.translate(table))  # 输出 '123'
    

字符串检查与判断

  • isalnum() : 如果字符串只包含字母和数字,返回 True

    text = 'hello123'
    print(text.isalnum())  # 输出 True
    
  • isalpha() : 如果字符串只包含字母,返回 True

    text = 'hello'
    print(text.isalpha())  # 输出 True
    
  • isascii() : 如果字符串中的所有字符都是 ASCII 字符,返回 True

    text = 'hello'
    print(text.isascii())  # 输出 True
    
  • isdecimal() : 如果字符串只包含十进制字符,返回 True

    text = '12345'
    print(text.isdecimal())  # 输出 True
    
  • isdigit() : 如果字符串只包含数字字符,返回 True

    text = '12345'
    print(text.isdigit())  # 输出 True
    
  • isidentifier() : 如果字符串是一个合法的标识符,返回 True

    text = 'hello'
    print(text.isidentifier())  # 输出 True
    
  • islower() : 如果字符串中的所有字母都是小写字母,返回 True

    text = 'hello'
    print(text.islower())  # 输出 True
    
  • isnumeric() : 如果字符串只包含数字字符,返回 True

    text = '12345'
    print(text.isnumeric())  # 输出 True
    
  • isprintable() : 如果字符串中的所有字符都是可打印的,返回 True

    text = 'hello'
    print(text.isprintable())  # 输出 True
    
  • isupper() : 如果字符串中的所有字母都是大写字母,返回 True

    text = 'HELLO'
    print(text.isupper())  # 输出 True
    

5. 字节

在 Python 中,字节类型(bytes)用于表示二进制数据。字节类型是不可变的,而可变字节类型(bytearray)是可变的。

创建

# 使用字节字面量
b = b'hello'

# 使用 bytes() 函数
b = bytes("hello", "utf-8")

# 使用 bytearray() 函数
ba = bytearray("hello", "utf-8")

访问

b = b'hello'
print(b[0])  # 输出: 104
print(b[1:3])  # 输出: b'el'

修改(仅适用于 bytearray)

ba = bytearray(b'hello')
ba[0] = 72  # 修改第一个字节
print(ba)  # 输出: bytearray(b'Hello')

常见方法

  • decode() :将字节数据解码为字符串。
b = b'hello'
s = b.decode("utf-8")
print(s)  # 输出: hello
  • hex() :将字节数据转换为十六进制字符串。
b = b'hello'
print(b.hex())  # 输出: 68656c6c6f

6. 列表

创建

Python 中创建列表有多种方式,下面是一些常见的用法:

空列表

empty_list = []

empty_list = list()

字面量初始化创建

fruits = ["apple", "banana", "cherry"]

从其他可迭代对象转换

numbers = list(range(5))  # [0, 1, 2, 3, 4]

tuple_data = (1, 2, 3)
list_from_tuple = list(tuple_data)  # [1, 2, 3]

string_data = "hello"
list_from_string = list(string_data)  # ['h', 'e', 'l', 'l', 'o']

使用列表推导式创建列表

squares = [x**2 for x in range(5)]  # [0, 1, 4, 9, 16]

添加

append()

将一个元素添加到列表的末尾。

fruits = ["apple", "banana"]
fruits.append("cherry")  # ['apple', 'banana', 'cherry']

extend()

将另一个可迭代对象的所有元素添加到列表的末尾。

fruits = ["apple", "banana"]
fruits.extend(["cherry", "date"])  # ['apple', 'banana', 'cherry', 'date']

insert()

将一个元素插入到指定的索引位置。如果索引超出范围,元素将被添加到末尾。

fruits = ["apple", "banana"]
fruits.insert(1, "cherry")  # ['apple', 'cherry', 'banana']

+ 运算符

将一个列表的所有元素添加到另一个列表中,生成一个新的列表。

list1 = [1, 2]
list2 = [3, 4]
merged_list = list1 + list2  # [1, 2, 3, 4]

* 运算符

将列表的内容重复指定次数。

numbers = [1, 2]
repeated_list = numbers * 3  # [1, 2, 1, 2, 1, 2]

+= 运算符

将另一个可迭代对象中的元素添加到现有列表的末尾。

fruits = ["apple", "banana"]
fruits += ["cherry", "date"]  # ['apple', 'banana', 'cherry', 'date']

列表推导式

根据条件添加多个元素。

numbers = [x for x in range(5)]  # [0, 1, 2, 3, 4]

numbers = [x for x in range(5) if x > 2]  # [3, 4]

使用 append() 添加多个元素

可以将一个列表作为单个元素添加进列表(这会生成嵌套的列表)。

fruits = ["apple", "banana"]
fruits.append(["cherry", "date"])  # ['apple', 'banana', ['cherry', 'date']]

删除

remove()

删除列表中第一次出现的指定元素。如果元素不存在,抛出 ValueError 异常。

fruits = ["apple", "banana", "cherry"]
fruits.remove("banana")  # ['apple', 'cherry']

pop()

根据索引删除并返回该位置的元素。若不指定索引,则默认删除并返回最后一个元素。

fruits = ["apple", "banana", "cherry"]
removed_item = fruits.pop(1)  # 删除索引为 1 的元素,返回 'banana'
print(fruits)  # ['apple', 'cherry']

# 如果不传递索引,则默认删除最后一个元素
last_item = fruits.pop()  # 返回 'cherry'
print(fruits)  # ['apple']

del 关键字

根据索引删除指定元素,或者删除切片中的一部分。del 不返回删除的元素。

fruits = ["apple", "banana", "cherry"]
del fruits[1]  # 删除索引为 1 的元素
print(fruits)  # ['apple', 'cherry']

# 删除整个列表
del fruits  # 完全删除列表

# 删除切片
fruits = ["apple", "banana", "cherry", "date"]
del fruits[1:3]  # 删除索引 1 到 2 的元素
print(fruits)  # ['apple', 'date']

clear()

删除列表中的所有元素。

fruits = ["apple", "banana", "cherry"]
fruits.clear()  # []

列表推导式

列表推导式可以根据条件生成新列表,删除不符合条件的元素。

fruits = ["apple", "banana", "cherry", "date"]
fruits = [fruit for fruit in fruits if fruit != "banana"]  # 删除 "banana"
print(fruits)  # ['apple', 'cherry', 'date']

filter()

可以根据条件过滤元素,返回一个新的迭代器。

fruits = ["apple", "banana", "cherry", "date"]
fruits = list(filter(lambda x: x != "banana", fruits))  # 删除 "banana"
print(fruits)  # ['apple', 'cherry', 'date']

获取

索引

索引用于访问列表中的单个元素。Python 中的列表索引是基于 0 的,也就是说,第一个元素的索引为 0,第二个为 1,以此类推。

允许使用负数索引,负数索引表示从列表的末尾开始计数,-1 表示最后一个元素,-2 表示倒数第二个元素,依此类推。

# 正向索引
fruits = ["apple", "banana", "cherry", "date"]
print(fruits[0])  # 'apple' - 第一个元素
print(fruits[1])  # 'banana' - 第二个元素

# 负向索引
fruits = ["apple", "banana", "cherry", "date"]
print(fruits[-1])  # 'date' - 最后一个元素

切片

切片用于访问列表中的一部分元素,可以通过指定起始索引和结束索引来提取列表的子集。切片返回一个新的列表。

基本切片语法

list[start:end:step]
  • start:切片的起始索引(包含)。
  • end:切片的结束索引(不包含)。
  • step:步长,默认为 1。步长大于 1 时,表示每隔若干个元素取一个。
fruits = ["apple", "banana", "cherry", "date", "elderberry"]

# 从索引 1 到 3(不包括 3),即 'banana', 'cherry'
print(fruits[1:3])  # ['banana', 'cherry']

# 从索引 2 到列表结束,取 'cherry', 'date', 'elderberry'
print(fruits[2:])  # ['cherry', 'date', 'elderberry']

# 从列表开头到索引 3(不包括 3),取 'apple', 'banana', 'cherry'
print(fruits[:3])  # ['apple', 'banana', 'cherry']

# 从索引 1 到 4,步长为 2,取 'banana' 和 'date'
print(fruits[1:4:2])  # ['banana', 'date']

# 复制整个列表(不指定任何参数)
print(fruits[:])  # ['apple', 'banana', 'cherry', 'date', 'elderberry']

# 使用负数索引进行切片,从倒数第三个元素到倒数第一个元素,取 'cherry', 'date'
print(fruits[-3:])  # ['cherry', 'date', 'elderberry']

切片的特殊情况

startend 超出列表的范围时,Python 会自动调整:

  • 如果 start 大于列表长度,则返回空列表。

  • 如果 end 超出列表长度,则返回列表的剩余部分。

    fruits = ["apple", "banana", "cherry"]
    
    # start 超过列表长度
    print(fruits[5:])  # [] - 超过范围,返回空列表
    
    # end 超过列表长度
    print(fruits[1:5])  # ['banana', 'cherry'] - 返回到列表末尾
    
  • 步长为负数的情况: 当步长为负数时,切片将从列表的右侧开始读取,start 必须大于 end,否则返回空列表。

    fruits = ["apple", "banana", "cherry", "date", "elderberry"]
    
    # 从右侧开始,每次步长为 -1,倒序取元素
    print(fruits[::-1])  # ['elderberry', 'date', 'cherry', 'banana', 'apple']
    
    # 从倒数第三个元素到倒数第一个元素,步长为 -1
    print(fruits[-3:-1])  # ['cherry', 'date']
    
    # 从倒数第一个元素到倒数第四个元素,步长为 -2
    print(fruits[-1:-4:-2])  # ['elderberry', 'cherry']
    

修改

通过获取到的索引或切片直接通过 = 赋值即可。

fruits = ["apple", "banana", "cherry", "date", "elderberry"]
fruits[0] = ["pear"]  # 替换索引元素
fruits[2:3] = ["orange", "pear"]  # 替换切片元素

其他

查找元素

  • index() :返回指定元素在列表中的第一个索引位置。如果元素不存在,抛出 ValueError 异常。
fruits = ["apple", "banana", "cherry"]
print(fruits.index("banana"))  # 输出: 1
# 如果元素不存在,抛出异常
# print(fruits.index("pear"))  # ValueError: 'pear' is not in list
  • in:检查某个元素是否在列表中,返回布尔值。
fruits = ["apple", "banana", "cherry"]
print("banana" in fruits)  # True
print("pear" in fruits)  # False

长度数量

  • len() :返回列表中元素的个数。
fruits = ["apple", "banana", "cherry"]
print(len(fruits))  # 输出: 3
  • count() :返回某个元素在列表中出现的次数。
fruits = ["apple", "banana", "cherry", "banana"]
print(fruits.count("banana"))  # 输出: 2
print(fruits.count("apple"))  # 输出: 1

排序反转

  • sort() :对列表进行原地排序,默认按升序排列。对于字符串,按照字母顺序排序。排序是就地修改列表。
numbers = [4, 1, 3, 2]
numbers.sort()  # 升序排列
print(numbers)  # 输出: [1, 2, 3, 4]

# 降序排列
numbers.sort(reverse=True)
print(numbers)  # 输出: [4, 3, 2, 1]
  • sorted() :返回一个新的已排序列表,而不修改原列表。
numbers = [4, 1, 3, 2]
sorted_numbers = sorted(numbers)
print(sorted_numbers)  # 输出: [1, 2, 3, 4]
print(numbers)  # 原列表不变: [4, 1, 3, 2]
  • reverse() :就地反转列表的元素。
复制编辑
fruits = ["apple", "banana", "cherry"]
fruits.reverse()  # 反转列表
print(fruits)  # 输出: ['cherry', 'banana', 'apple']
  • reversed() :返回一个反转后的迭代器,可以用于创建反转后的新列表。
fruits = ["apple", "banana", "cherry"]
reversed_fruits = list(reversed(fruits))  # 返回一个新的反转列表
print(reversed_fruits)  # 输出: ['cherry', 'banana', 'apple']

拷贝

在 Python 中,列表拷贝指的是创建一个新的列表,其元素与原始列表相同,但在内存中是不同的对象。拷贝的方式有很多种,下面我会介绍几种常用的方式,并说明它们的区别。

1. copy()

copy() 方法创建一个浅拷贝(shallow copy),它会创建一个新的列表,但如果列表中包含可变对象(如子列表、字典等),这些可变对象的引用会被复制,而不是创建新的副本。

fruits = ["apple", "banana", "cherry"]
fruits_copy = fruits.copy()
print(fruits_copy)  # 输出: ['apple', 'banana', 'cherry']

2. 使用切片操作 [:]

  • 切片操作 [:] 也能创建一个浅拷贝,效果与 copy() 方法相同。
  • 使用切片的方式是将整个列表截取出来,实际上会返回一个新的列表对象。
fruits = ["apple", "banana", "cherry"]
fruits_copy = fruits[:]
print(fruits_copy)  # 输出: ['apple', 'banana', 'cherry']

3. 使用 list() 构造函数

list() 函数可以将任何可迭代对象(如元组、集合、字符串等)转换为列表,使用该函数可以创建列表的浅拷贝。

fruits = ["apple", "banana", "cherry"]
fruits_copy = list(fruits)
print(fruits_copy)  # 输出: ['apple', 'banana', 'cherry']

4. 使用 copy 模块的 copy() 函数

copy 模块提供了一个 copy() 函数,可以用于创建浅拷贝。它与 list.copy() 方法或切片操作 [:] 类似。

import copy
fruits = ["apple", "banana", "cherry"]
fruits_copy = copy.copy(fruits)
print(fruits_copy)  # 输出: ['apple', 'banana', 'cherry']

5. 深拷贝(Deep Copy)

如果列表中包含其他可变对象(如子列表、字典等),使用浅拷贝(如 copy()[:])会复制对象的引用,而不是创建新对象。这会导致修改其中一个列表时,另一个列表的相关部分也被修改。

如果需要完全独立的列表(包括嵌套对象),可以使用深拷贝(deep copy)。Python 的 copy 模块提供了 deepcopy() 函数,可以创建深拷贝。

import copy

# 列表包含子列表
fruits = ["apple", ["banana", "cherry"], "date"]
fruits_copy = copy.deepcopy(fruits)

# 修改原始列表中的子列表元素
fruits[1][0] = "blueberry"

print(fruits)          # 输出: ['apple', ['blueberry', 'cherry'], 'date']
print(fruits_copy)     # 输出: ['apple', ['banana', 'cherry'], 'date']

区别

  • 浅拷贝copy()、切片 [:]list()copy.copy())会创建一个新的列表,但如果列表中有其他可变对象(如子列表、字典等),它们会被共享,即修改其中一个列表中的可变对象会影响到另一个列表。
  • 深拷贝copy.deepcopy())会递归地创建所有元素的副本,包括嵌套的可变对象,确保两个列表完全独立。
import copy

# 浅拷贝示例
original = [1, [2, 3]]
shallow_copy = copy.copy(original)

# 修改原始列表中的子列表
original[1][0] = 99

print(original)       # 输出: [1, [99, 3]]
print(shallow_copy)   # 输出: [1, [99, 3]]  # 浅拷贝也受影响

# 深拷贝示例
deep_copy = copy.deepcopy(original)

# 修改原始列表中的子列表
original[1][0] = 100

print(original)       # 输出: [1, [100, 3]]
print(deep_copy)      # 输出: [1, [99, 3]]  # 深拷贝不受影响

7. 元组

创建

Python 中创建元组有多种方式,下面是一些常见的用法:

空元组

empty_tuple = ()
empty_tuple = tuple()

字面量初始化创建

fruits = ("apple", "banana", "cherry")

从其他可迭代对象转换

numbers = tuple(range(5))  # (0, 1, 2, 3, 4)

list_data = [1, 2, 3]
tuple_from_list = tuple(list_data)  # (1, 2, 3)

string_data = "hello"
tuple_from_string = tuple(string_data)  # ('h', 'e', 'l', 'l', 'o')

单元素元组

single_element_tuple = ("apple",)  # 注意逗号

访问

索引

索引用于访问元组中的单个元素。Python 中的元组索引是基于 0 的,也就是说,第一个元素的索引为 0,第二个为 1,以此类推。

允许使用负数索引,负数索引表示从元组的末尾开始计数,-1 表示最后一个元素,-2 表示倒数第二个元素,依此类推。

# 正向索引
fruits = ("apple", "banana", "cherry", "date")
print(fruits[0])  # 'apple' - 第一个元素
print(fruits[1])  # 'banana' - 第二个元素

# 负向索引
fruits = ("apple", "banana", "cherry", "date")
print(fruits[-1])  # 'date' - 最后一个元素

切片

切片用于访问元组中的一部分元素,可以通过指定起始索引和结束索引来提取元组的子集。切片返回一个新的元组。

基本切片语法

tuple[start:end:step]
  • start:切片的起始索引(包含)。
  • end:切片的结束索引(不包含)。
  • step:步长,默认为 1。步长大于 1 时,表示每隔若干个元素取一个。
fruits = ("apple", "banana", "cherry", "date", "elderberry")

# 从索引 1 到 3(不包括 3),即 'banana', 'cherry'
print(fruits[1:3])  # ('banana', 'cherry')

# 从索引 2 到元组结束,取 'cherry', 'date', 'elderberry'
print(fruits[2:])  # ('cherry', 'date', 'elderberry')

# 从元组开头到索引 3(不包括 3),取 'apple', 'banana', 'cherry'
print(fruits[:3])  # ('apple', 'banana', 'cherry')

# 从索引 1 到 4,步长为 2,取 'banana' 和 'date'
print(fruits[1:4:2])  # ('banana', 'date')

# 复制整个元组(不指定任何参数)
print(fruits[:])  # ('apple', 'banana', 'cherry', 'date', 'elderberry')

# 使用负数索引进行切片,从倒数第三个元素到倒数第一个元素,取 'cherry', 'date'
print(fruits[-3:])  # ('cherry', 'date', 'elderberry')

切片的特殊情况

startend 超出元组的范围时,Python 会自动调整:

  • 如果 start 大于元组长度,则返回空元组。

  • 如果 end 超出元组长度,则返回元组的剩余部分。

    fruits = ("apple", "banana", "cherry")
    
    # start 超过元组长度
    print(fruits[5:])  # () - 超过范围,返回空元组
    
    # end 超过元组长度
    print(fruits[1:5])  # ('banana', 'cherry') - 返回到元组末尾
    
  • 步长为负数的情况: 当步长为负数时,切片将从元组的右侧开始读取,start 必须大于 end,否则返回空元组。

    fruits = ("apple", "banana", "cherry", "date", "elderberry")
    
    # 从右侧开始,每次步长为 -1,倒序取元素
    print(fruits[::-1])  # ('elderberry', 'date', 'cherry', 'banana', 'apple')
    
    # 从倒数第三个元素到倒数第一个元素,步长为 -1
    print(fruits[-3:-1])  # ('cherry', 'date')
    
    # 从倒数第一个元素到倒数第四个元素,步长为 -2
    print(fruits[-1:-4:-2])  # ('elderberry', 'cherry')
    

其他

查找元素

  • index() :返回指定元素在元组中的第一个索引位置。如果元素不存在,抛出 ValueError 异常。
fruits = ("apple", "banana", "cherry")
print(fruits.index("banana"))  # 输出: 1
# 如果元素不存在,抛出异常
# print(fruits.index("pear"))  # ValueError: 'pear' is not in tuple
  • in:检查某个元素是否在元组中,返回布尔值。
fruits = ("apple", "banana", "cherry")
print("banana" in fruits)  # True
print("pear" in fruits)  # False

长度数量

  • len() :返回元组中元素的个数。
fruits = ("apple", "banana", "cherry")
print(len(fruits))  # 输出: 3
  • count() :返回某个元素在元组中出现的次数。
fruits = ("apple", "banana", "cherry", "banana")
print(fruits.count("banana"))  # 输出: 2
print(fruits.count("apple"))  # 输出: 1

连接与重复

  • + 运算符:将两个元组连接起来,生成一个新的元组。
tuple1 = (1, 2)
tuple2 = (3, 4)
merged_tuple = tuple1 + tuple2  # (1, 2, 3, 4)
  • * 运算符:将元组的内容重复指定次数。
numbers = (1, 2)
repeated_tuple = numbers * 3  # (1, 2, 1, 2, 1, 2)

不可变性

元组是不可变的,这意味着一旦创建,就不能修改其内容。如果需要修改元组,可以将其转换为列表,进行修改后再转换回元组。

fruits = ("apple", "banana", "cherry")
fruits_list = list(fruits)
fruits_list[0] = "pear"
fruits = tuple(fruits_list)
print(fruits)  # ('pear', 'banana', 'cherry')

解包

元组解包允许将元组中的元素直接赋值给多个变量。

fruits = ("apple", "banana", "cherry")
a, b, c = fruits
print(a)  # 'apple'
print(b)  # 'banana'
print(c)  # 'cherry'

嵌套元组

元组可以包含其他元组,形成嵌套结构。

nested_tuple = (1, (2, 3), (4, (5, 6)))
print(nested_tuple[1])  # (2, 3)
print(nested_tuple[2][1])  # (5, 6)

元组与列表的区别

  • 元组是不可变的,而列表是可变的。
  • 元组使用小括号 (),列表使用方括号 []
  • 元组通常用于存储异构数据(不同类型的数据),而列表通常用于存储同构数据(相同类型的数据)。
# 元组
person = ("Alice", 30, "Engineer")

# 列表
numbers = [1, 2, 3, 4, 5]

8. 字典

创建

Python 中创建字典有多种方式,下面是一些常见的用法:

空字典

empty_dict = {}
empty_dict = dict()

字面量初始化创建

person = {"name": "Alice", "age": 30, "job": "Engineer"}

使用 dict() 构造函数

person = dict(name="Alice", age=30, job="Engineer")

从键值对序列创建

pairs = [("name", "Alice"), ("age", 30), ("job", "Engineer")]
person = dict(pairs)

访问

通过键访问值

person = {"name": "Alice", "age": 30, "job": "Engineer"}
print(person["name"])  # 输出: Alice

使用 get() 方法

person = {"name": "Alice", "age": 30, "job": "Engineer"}
print(person.get("name"))  # 输出: Alice
print(person.get("salary", "Not specified"))  # 输出: Not specified

修改

添加或更新键值对

person = {"name": "Alice", "age": 30}
person["job"] = "Engineer"  # 添加新键值对
person["age"] = 31  # 更新已有键值对

使用 update() 方法

person = {"name": "Alice", "age": 30}
person.update({"age": 31, "job": "Engineer"})

删除

使用 del 关键字

person = {"name": "Alice", "age": 30, "job": "Engineer"}
del person["age"]

使用 pop() 方法

person = {"name": "Alice", "age": 30, "job": "Engineer"}
age = person.pop("age")

使用 popitem() 方法

person = {"name": "Alice", "age": 30, "job": "Engineer"}
item = person.popitem()  # 随机删除一个键值对

使用 clear() 方法

person = {"name": "Alice", "age": 30, "job": "Engineer"}
person.clear()

其他

查找键值对

  • keys() :返回字典中所有键的视图。
person = {"name": "Alice", "age": 30, "job": "Engineer"}
print(person.keys())  # 输出: dict_keys(['name', 'age', 'job'])
  • values() :返回字典中所有值的视图。
person = {"name": "Alice", "age": 30, "job": "Engineer"}
print(person.values())  # 输出: dict_values(['Alice', 30, 'Engineer'])
  • items() :返回字典中所有键值对的视图。
person = {"name": "Alice", "age": 30, "job": "Engineer"}
print(person.items())  # 输出: dict_items([('name', 'Alice'), ('age', 30), ('job', 'Engineer')])

长度

  • len() :返回字典中键值对的数量。
person = {"name": "Alice", "age": 30, "job": "Engineer"}
print(len(person))  # 输出: 3

字典合并

  • update() :将一个字典的键值对更新到另一个字典中。
person = {"name": "Alice", "age": 30}
additional_info = {"job": "Engineer", "city": "New York"}
person.update(additional_info)
  • 字典解包:使用 ** 操作符合并字典。
person = {"name": "Alice", "age": 30}
additional_info = {"job": "Engineer", "city": "New York"}
merged_dict = {**person, **additional_info}

8. 集合

创建

Python 中创建集合有多种方式,下面是一些常见的用法:

空集合

empty_set = set()

字面量初始化创建

fruits = {"apple", "banana", "cherry"}

从其他可迭代对象转换

numbers = set(range(5))  # {0, 1, 2, 3, 4}

list_data = [1, 2, 3]
set_from_list = set(list_data)  # {1, 2, 3}

string_data = "hello"
set_from_string = set(string_data)  # {'h', 'e', 'l', 'o'}

添加

add()

将一个元素添加到集合中。

fruits = {"apple", "banana"}
fruits.add("cherry")

update()

将另一个可迭代对象的所有元素添加到集合中。

fruits = {"apple", "banana"}
fruits.update(["cherry", "date"])

删除

remove()

删除集合中的指定元素。如果元素不存在,抛出 KeyError 异常。

fruits = {"apple", "banana", "cherry"}
fruits.remove("banana")

discard()

删除集合中的指定元素。如果元素不存在,不会抛出异常。

fruits = {"apple", "banana", "cherry"}
fruits.discard("banana")

pop()

随机删除并返回集合中的一个元素。

fruits = {"apple", "banana", "cherry"}
removed_item = fruits.pop()

clear()

删除集合中的所有元素。

fruits = {"apple", "banana", "cherry"}
fruits.clear()

集合运算

并集

  • union() :返回两个集合的并集。
set1 = {1, 2, 3}
set2 = {3, 4, 5}
union_set = set1.union(set2)  # {1, 2, 3, 4, 5}
  • | 运算符:返回两个集合的并集。
set1 = {1, 2, 3}
set2 = {3, 4, 5}
union_set = set1 | set2  # {1, 2, 3, 4, 5}

交集

  • intersection() :返回两个集合的交集。
set1 = {1, 2, 3}
set2 = {3, 4, 5}
intersection_set = set1.intersection(set2)  # {3}
  • & 运算符:返回两个集合的交集。
set1 = {1, 2, 3}
set2 = {3, 4, 5}
intersection_set = set1 & set2  # {3}

差集

  • difference() :返回两个集合的差集。
set1 = {1, 2, 3}
set2 = {3, 4, 5}
difference_set = set1.difference(set2)  # {1, 2}
  • - 运算符:返回两个集合的差集。
set1 = {1, 2, 3}
set2 = {3, 4, 5}
difference_set = set1 - set2  # {1, 2}

对称差集

  • symmetric_difference() :返回两个集合的对称差集。
set1 = {1, 2, 3}
set2 = {3, 4, 5}
symmetric_difference_set = set1.symmetric_difference(set2)  # {1, 2, 4, 5}
  • ^ 运算符:返回两个集合的对称差集。
set1 = {1, 2, 3}
set2 = {3, 4, 5}
symmetric_difference_set = set1 ^ set2  # {1, 2, 4, 5}

其他

查找元素

  • in:检查某个元素是否在集合中,返回布尔值。
fruits = {"apple", "banana", "cherry"}
print("banana" in fruits)  # True
print("pear" in fruits)  # False

长度

  • len() :返回集合中元素的数量。
fruits = {"apple", "banana", "cherry"}
print(len(fruits))  # 输出: 3

集合比较

  • issubset() :检查一个集合是否是另一个集合的子集。
set1 = {1, 2, 3}
set2 = {1, 2}
print(set2.issubset(set1))  # True
  • issuperset() :检查一个集合是否是另一个集合的超集。
set1 = {1, 2, 3}
set2 = {1, 2}
print(set1.issuperset(set2))  # True
  • isdisjoint() :检查两个集合是否没有交集。
set1 = {1, 2, 3}
set2 = {4, 5, 6}
print(set1.isdisjoint(set2))  # True

9. 总结

对比

数据类型描述可变性有序性
None表示空值或无值不可变/
bool布尔类型,表示真或假不可变/
int整数类型不可变/
float浮点数类型不可变/
complex复数类型不可变/
str字符串类型不可变/
list列表类型,可变序列可变有序
tuple元组类型,不可变序列不可变/
dict字典类型,键值对集合可变有序(Python 3.7+)
set集合类型,无序不重复元素可变无序
bytes字节类型不可变有序
bytearray可变字节类型可变有序

转换

函数描述示例
int(x)将 x 转换为整数int("42") -> 42
float(x)将 x 转换为浮点数float("3.14") -> 3.14
complex(x)将 x 转换为复数complex(1, 2) -> (1+2j)
str(x)将 x 转换为字符串str(42) -> "42"
list(x)将 x 转换为列表list((1, 2, 3)) -> [1, 2, 3]
tuple(x)将 x 转换为元组tuple([1, 2, 3]) -> (1, 2, 3)
dict(x)将 x 转换为字典dict([("key", "value")]) -> {"key": "value"}
set(x)将 x 转换为集合set([1, 2, 3]) -> {1, 2, 3}
bool(x)将 x 转换为布尔值bool(1) -> True
bytes(x)将 x 转换为字节bytes("hello", "utf-8") -> b'hello'
bytearray(x)将 x 转换为可变字节bytearray("hello", "utf-8") -> bytearray(b'hello')