pin_drop当前位置:知识文库 ❯ 图文
Python len()函数 字符串列表字典长度获取
一、函数概述
Python内置函数len()用于获取对象的长度或元素个数,是Python中最常用的内置函数之一。它支持所有内置容器类型(字符串、列表、元组、字典、集合等),并可通过实现__len__魔术方法扩展到自定义类。
-
通用性:支持所有内置容器类型
-
O(1)复杂度:内置容器获取长度是常数时间
-
可扩展:自定义类实现__len__即可使用len()
-
条件判断:空容器len()为0,在布尔上下文中为False
二、语法详解
三、len()基础用法
示例1:字符串长度
代码示例
# 基本字符串
text1 = "hello"
print(f"'hello' 的长度: {len(text1)}")
# 空字符串
text2 = ""
print(f"空字符串长度: {len(text2)}")
# 包含空格和标点
text3 = "hello world!"
print(f"'hello world!' 的长度: {len(text3)}")
# 中文字符(每个中文字符算1个)
text4 = "你好世界"
print(f"'你好世界' 的长度: {len(text4)}")
# 转义字符(\n、\t各算1个字符)
text5 = "a\nb\tc"
print(f"'a\\nb\\tc' 的长度: {len(text5)}")
输出结果:
代码示例
'hello' 的长度: 5
空字符串长度: 0
'hello world!' 的长度: 12
'你好世界' 的长度: 4
'a\nb\tc' 的长度: 5
示例2:列表与元组长度
代码示例
# 列表
empty_list = []
numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True]
nested = [[1, 2], [3, 4], [5, 6]]
print(f"空列表长度: {len(empty_list)}")
print(f"numbers长度: {len(numbers)}")
print(f"mixed长度: {len(mixed)}")
print(f"nested长度: {len(nested)}") # 注意:只计算外层元素
# 元组
empty_tuple = ()
point = (3, 4)
colors = ("红", "绿", "蓝")
print(f"\n空元组长度: {len(empty_tuple)}")
print(f"point长度: {len(point)}")
print(f"colors长度: {len(colors)}")
# 单元素元组(注意逗号)
single = (42,)
print(f"single长度: {len(single)}")
输出结果:
代码示例
空列表长度: 0
numbers长度: 5
mixed长度: 4
nested长度: 3
空元组长度: 0
point长度: 2
colors长度: 3
single长度: 1
示例3:字典与集合长度
代码示例
# 字典(键值对数量)
empty_dict = {}
student = {"name": "张三", "age": 20, "grade": "A"}
nested_dict = {"a": {"b": 1}, "c": {"d": 2}}
print(f"空字典长度: {len(empty_dict)}")
print(f"student长度: {len(student)}")
print(f"nested_dict长度: {len(nested_dict)}") # 只计算顶层键
# 集合(去重后的元素数量)
empty_set = set()
unique_nums = {1, 2, 3, 3, 2, 1}
fruits = {"苹果", "香蕉", "橘子"}
print(f"\n空集合长度: {len(empty_set)}")
print(f"unique_nums长度: {len(unique_nums)}") # 去重后
print(f"fruits长度: {len(fruits)}")
输出结果:
代码示例
空字典长度: 0
student长度: 3
nested_dict长度: 2
空集合长度: 0
unique_nums长度: 3
fruits长度: 3
四、各类数据结构的len()
示例1:range与bytes
代码示例
# range对象
r1 = range(10)
r2 = range(2, 10)
r3 = range(0, 20, 3)
print(f"range(10) 长度: {len(r1)}")
print(f"range(2, 10) 长度: {len(r2)}")
print(f"range(0, 20, 3) 长度: {len(r3)}")
# bytes对象
b1 = b"hello"
b2 = bytes([65, 66, 67])
b3 = b""
print(f"\nb'hello' 长度: {len(b1)}")
print(f"bytes([65,66,67]) 长度: {len(b2)}")
print(f"空bytes长度: {len(b3)}")
# bytearray(可变的字节序列)
ba = bytearray(b"abc")
print(f"bytearray长度: {len(ba)}")
输出结果:
代码示例
range(10) 长度: 10
range(2, 10) 长度: 8
range(0, 20, 3) 长度: 7
b'hello' 长度: 5
bytes([65,66,67]) 长度: 3
空bytes长度: 0
bytearray长度: 3
示例2:嵌套结构的长度
代码示例
# 注意:len()只计算最外层元素个数
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
print(f"矩阵外层长度: {len(matrix)}")
print(f"第一行长度: {len(matrix[0])}")
# 计算总元素数(需要遍历)
total = sum(len(row) for row in matrix)
print(f"矩阵总元素数: {total}")
# 嵌套字典
data = {
"users": [
{"name": "张三", "age": 25},
{"name": "李四", "age": 30}
],
"count": 2
}
print(f"\ndata顶层键数量: {len(data)}")
print(f"users列表长度: {len(data['users'])}")
输出结果:
代码示例
矩阵外层长度: 3
第一行长度: 3
矩阵总元素数: 9
data顶层键数量: 2
users列表长度: 2
五、__len__魔术方法
示例1:实现自定义容器的len()
代码示例
class ShoppingCart:
def __init__(self):
self.items = []
def add(self, name, price):
self.items.append({"name": name, "price": price})
def __len__(self):
return len(self.items)
def __bool__(self):
return len(self.items) > 0
cart = ShoppingCart()
print(f"空购物车长度: {len(cart)}")
print(f"空购物车布尔值: {bool(cart)}")
cart.add("笔记本电脑", 5999)
cart.add("鼠标", 99)
cart.add("键盘", 199)
print(f"\n添加商品后长度: {len(cart)}")
print(f"购物车布尔值: {bool(cart)}")
输出结果:
代码示例
空购物车长度: 0
空购物车布尔值: False
添加商品后长度: 3
购物车布尔值: True
示例2:动态计算长度
代码示例
class EvenNumbers:
"""只存储偶数的集合"""
def __init__(self, limit):
self.limit = limit
def __len__(self):
# 动态计算,不实际存储
return self.limit // 2
def __contains__(self, n):
return n % 2 == 0 and 0 <= n < self.limit
evens = EvenNumbers(20)
print(f"0-19中偶数个数: {len(evens)}") # 10个:0,2,4,6,8,10,12,14,16,18
evens100 = EvenNumbers(100)
print(f"0-99中偶数个数: {len(evens100)}") # 50个
输出结果:
代码示例
0-19中偶数个数: 10
0-99中偶数个数: 50
示例3:组合多个容器的长度
代码示例
class MultiContainer:
def __init__(self):
self.lists = []
def add_list(self, lst):
self.lists.append(lst)
def __len__(self):
# 返回所有列表元素的总数
return sum(len(lst) for lst in self.lists)
def container_count(self):
return len(self.lists)
mc = MultiContainer()
mc.add_list([1, 2, 3])
mc.add_list([4, 5])
mc.add_list([6, 7, 8, 9])
print(f"容器数量: {mc.container_count()}")
print(f"总元素数: {len(mc)}") # 3 + 2 + 4 = 9
输出结果:
代码示例
容器数量: 3
总元素数: 9
六、len()的高级应用
示例1:条件判断与边界检查
代码示例
def process_data(data, max_size=100):
"""处理数据,带有长度检查"""
length = len(data)
if length == 0:
print("错误: 数据为空")
return None
if length > max_size:
print(f"警告: 数据长度{length}超过最大值{max_size}")
data = data[:max_size]
print(f"处理{len(data)}个元素...")
return data
# 测试
print("--- 空数据 ---")
process_data([])
print("\n--- 正常数据 ---")
process_data([1, 2, 3, 4, 5])
print("\n--- 超大数 ---")
process_data(list(range(200)))
输出结果:
代码示例
--- 空数据 ---
错误: 数据为空
--- 正常数据 ---
处理5个元素...
--- 超大数 ---
警告: 数据长度200超过最大值100
处理100个元素...
示例2:len()在循环中的使用
代码示例
# 传统索引遍历
fruits = ["苹果", "香蕉", "橘子", "葡萄"]
print("--- 使用len()控制循环 ---")
for i in range(len(fruits)):
print(f"{i}: {fruits[i]}")
# 更Pythonic的方式(推荐)
print("\n--- enumerate方式(推荐)---")
for i, fruit in enumerate(fruits):
print(f"{i}: {fruit}")
# 反向遍历
print("\n--- 反向遍历 ---")
for i in range(len(fruits) - 1, -1, -1):
print(f"{i}: {fruits[i]}")
# 最佳反向遍历方式
print("\n--- reversed方式(推荐)---")
for i, fruit in enumerate(reversed(fruits)):
print(f"倒数{i+1}: {fruit}")
输出结果:
代码示例
--- 使用len()控制循环 ---
0: 苹果
1: 香蕉
2: 橘子
3: 葡萄
--- enumerate方式(推荐)---
0: 苹果
1: 香蕉
2: 橘子
3: 葡萄
--- 反向遍历 ---
3: 葡萄
2: 橘子
1: 香蕉
0: 苹果
--- reversed方式(推荐)---
倒数1: 葡萄
倒数2: 橘子
倒数3: 香蕉
倒数4: 苹果
示例3:统计文件行数
代码示例
# 模拟文件内容
file_content = """第一行:Python教程
第二行:len()函数详解
第三行:示例代码
第四行:总结
""".strip().split("\n")
# 方法1:直接len()
print(f"文件行数: {len(file_content)}")
# 方法2:统计非空行
non_empty = sum(1 for line in file_content if line.strip())
print(f"非空行数: {non_empty}")
# 方法3:包含特定关键词的行
keyword_lines = sum(1 for line in file_content if "len" in line)
print(f"包含'len'的行数: {keyword_lines}")
输出结果:
代码示例
文件行数: 4
非空行数: 4
包含'len'的行数: 1
七、注意事项
注意1:len()不支持迭代器和生成器:迭代器和生成器没有固定的长度,因为它们可以产生无限元素或延迟计算。对它们使用len()会抛出TypeError。如需计算迭代器元素个数,需先转换为列表:
len(list(iterator))(会消耗迭代器)。
注意2:len()返回非负整数:
__len__方法必须返回非负整数。如果返回负数,len()会抛出ValueError。如果返回非整数类型,会抛出TypeError。
注意3:中文字符与字节长度:len()对字符串返回的是Unicode字符数,不是字节数。中文字符每个算1个。如果需要字节长度,需先编码:
len("中文".encode("utf-8"))返回6(UTF-8下每个中文3字节)。
注意4:__len__应为O(1)操作:根据Python规范,__len__方法应该是一个快速操作(最好O(1))。如果需要复杂计算才能确定长度,建议提供其他方法名(如count()、size())而不是实现__len__,以免误导使用者认为len()很快。
注意5:嵌套结构只计算顶层:len()只计算容器最外层的元素个数,不会递归计算嵌套结构中的元素。如
len([[1,2],[3,4]])返回2,不是4。需要递归计算时应自行实现。
小贴士
len()与布尔值的隐式转换:在Python中,如果一个类实现了__len__方法但没有实现__bool__,则bool(obj)会根据len(obj) != 0来判断。这意味着空容器在条件判断中自动为False,非空为True,非常便于编写if data:这样的简洁代码。
八、练习题
练习1
编写一个RecursiveLength类,提供递归计算嵌套结构长度的功能:
(1)total_length(obj):递归计算嵌套列表/元组中所有基本元素的总数
(2)depth(obj):计算嵌套的最大深度
(3)max_width(obj):计算任意层级的最大宽度
(4)测试:[1, [2, 3], [[4, 5], 6]] 的总长度、深度和最大宽度
练习2
编写一个FixedSizeQueue类,实现固定长度的队列:
(1)初始化时接收maxlen参数
(2)实现__len__返回当前元素个数
(3)实现push(item):添加元素,超出maxlen时移除最旧元素
(4)实现__bool__:队列非空返回True
(5)测试:创建maxlen=3的队列,添加5个元素,观察长度变化
常见问题
len()的时间复杂度是多少?
对于Python内置容器(list、str、dict、set等),len()的时间复杂度是O(1),因为它们在内部维护了长度信息。但对于自定义类,取决于__len__的实现。如果__len__需要遍历计算,则可能是O(n)。
为什么生成器和迭代器不能使用len()?
生成器和迭代器是惰性求值的,元素在被需要时才产生。它们可能产生无限序列,也可能在运行时才能确定有多少元素。因此没有固定的长度概念。如果需要知道元素个数,必须消费整个迭代器:sum(1 for _ in generator)。
len()可以返回负数吗?
不可以。Python规定__len__必须返回非负整数。如果返回负数,len()会抛出ValueError: __len__() should return >= 0。这是为了保证len()的语义一致性,长度不可能是负数。
如何判断对象是否支持len()?
可以使用hasattr检查:hasattr(obj, '__len__')。更规范的方式是使用collections.abc.Sized:isinstance(obj, collections.abc.Sized)。Sized抽象基类标记了所有支持len()的类型。
本文涉及AI创作
内容由AI创作,请仔细甄别