数据结构
数据结构可以理解为:
用什么方式组织、保存和处理数据。
例如,要保存一只股票的信息,可以使用不同的数据结构。
使用多个变量:
code = "600519"
name = "贵州茅台"
price = 1500.0
使用列表:
stock = ["600519", "贵州茅台", 1500.0]
使用字典:
stock = {
"code": "600519",
"name": "贵州茅台",
"price": 1500.0,
}
不同的数据结构,适合不同的场景。
Python 常用的数据结构有:
| 数据结构 | 类型 | 特点 |
|---|---|---|
| 字符串 | str |
有序、不可修改 |
| 列表 | list |
有序、可修改、可重复 |
| 元组 | tuple |
有序、不可修改、可重复 |
| 字典 | dict |
键值对、可修改、键不可重复 |
| 集合 | set |
无序、可修改、不可重复 |
字符串用于保存文本数据。
name = "Python"
stock_code = "600519"
message = "今天市场上涨"
字符串属于有序数据,可以通过索引访问其中的字符。
可以使用单引号:
name = 'Python'
也可以使用双引号:
name = "Python"
多行字符串可以使用三引号:
text = """
第一行
第二行
第三行
"""
字符串中的每个字符都有一个位置编号,称为索引。
text = "Python"
对应索引:
字符: P y t h o n
索引: 0 1 2 3 4 5
反向:-6 -5 -4 -3 -2 -1
访问第一个字符:
text = "Python"
print(text[0])
结果:
P
访问最后一个字符:
print(text[-1])
结果:
n
注意,索引从 0 开始。
切片用于获取字符串的一部分。
基本格式:
字符串[开始位置:结束位置:步长]
例如:
text = "Python"
print(text[0:3])
结果:
Pyt
切片包含开始位置,但不包含结束位置。
常见写法:
text = "Python"
print(text[:3]) # 前三个字符
print(text[3:]) # 从索引 3 到结尾
print(text[:]) # 整个字符串
print(text[::2]) # 每隔一个字符取一次
print(text[::-1]) # 反转字符串
结果:
Pyt
hon
Python
Pto
nohtyP
字符串创建后不能直接修改其中的字符。
错误示例:
text = "Python"
text[0] = "J"
会出现错误:
TypeError
正确做法是创建新字符串:
text = "Python"
text = "J" + text[1:]
print(text)
结果:
Jython
使用 +:
first_name = "张"
last_name = "三"
full_name = first_name + last_name
print(full_name)
结果:
张三
字符串重复:
print("Python" * 3)
结果:
PythonPythonPython
推荐使用 f-string:
name = "张三"
age = 25
message = f"姓名:{name},年龄:{age}"
print(message)
可以直接执行表达式:
price = 20
count = 5
print(f"总价:{price * count} 元")
控制小数位:
price = 12.34567
print(f"{price:.2f}")
结果:
12.35
text = " Python "
print(text.strip())
只删除左边:
text.lstrip()
只删除右边:
text.rstrip()
text = "Python"
print(text.lower())
print(text.upper())
结果:
python
PYTHON
首字母大写:
print("python".capitalize())
每个单词首字母大写:
print("hello python".title())
text = "Python is easy"
new_text = text.replace("easy", "powerful")
print(new_text)
结果:
Python is powerful
原字符串不会改变。
code = "600519"
print(code.startswith("60"))
print(code.endswith("19"))
结果:
True
True
股票代码判断:
if code.startswith(("00", "60")):
print("主板股票")
startswith() 可以接收元组。
text = "Python is easy"
print(text.find("easy"))
结果:
10
找不到时返回 -1:
print(text.find("Java"))
也可以使用成员运算符:
print("Python" in text)
print("Java" not in text)
codes = "600519,000001,300750"
code_list = codes.split(",")
print(code_list)
结果:
["600519", "000001", "300750"]
按空格分割:
text = "Python Java Go"
print(text.split())
限制分割次数:
text = "600519-贵州茅台-白酒"
print(text.split("-", maxsplit=1))
结果:
["600519", "贵州茅台-白酒"]
codes = ["600519", "000001", "300750"]
result = ",".join(codes)
print(result)
结果:
600519,000001,300750
注意,join() 的列表元素必须都是字符串。
错误:
numbers = [1, 2, 3]
",".join(numbers)
正确:
numbers = [1, 2, 3]
result = ",".join(str(number) for number in numbers)
print(result)
print("123456".isdigit())
print("Python".isalpha())
print("Python123".isalnum())
print(" ".isspace())
结果:
True
True
True
True
判断股票代码:
def is_valid_code(code: str) -> bool:
return len(code) == 6 and code.isdigit()
列表用于保存一组有顺序的数据。
列表的特点:
- 有顺序
- 可以修改
- 可以重复
- 可以保存不同类型的数据
创建列表:
stocks = ["贵州茅台", "比亚迪", "宁德时代"]
空列表:
stocks = []
也可以:
stocks = list()
保存多个数据:
numbers = [10, 20, 30]
保存不同类型:
data = ["600519", "贵州茅台", 1500.0, True]
虽然可以保存不同类型,但实际项目中通常建议保持元素结构一致。
stocks = ["贵州茅台", "比亚迪", "宁德时代"]
print(stocks[0])
print(stocks[-1])
结果:
贵州茅台
宁德时代
stocks = ["贵州茅台", "比亚迪", "宁德时代"]
stocks[1] = "中国平安"
print(stocks)
结果:
["贵州茅台", "中国平安", "宁德时代"]
列表是可修改的数据结构。
numbers = [10, 20, 30, 40, 50]
print(numbers[1:4])
print(numbers[:3])
print(numbers[2:])
print(numbers[::-1])
结果:
[20, 30, 40]
[10, 20, 30]
[30, 40, 50]
[50, 40, 30, 20, 10]
切片会创建一个新列表。
在列表末尾添加一个元素:
stocks = ["贵州茅台", "比亚迪"]
stocks.append("宁德时代")
print(stocks)
在指定位置插入元素:
stocks.insert(1, "中国平安")
第一个参数是插入位置。
一次添加多个元素:
stocks = ["贵州茅台"]
stocks.extend(["比亚迪", "宁德时代"])
print(stocks)
也可以使用 +:
stocks = ["贵州茅台"] + ["比亚迪", "宁德时代"]
区别是:
extend()修改原列表+创建新列表
按照值删除:
stocks = ["贵州茅台", "比亚迪", "宁德时代"]
stocks.remove("比亚迪")
如果元素不存在,会报错。
安全写法:
if "比亚迪" in stocks:
stocks.remove("比亚迪")
按照索引删除,并返回被删除的元素:
stocks = ["贵州茅台", "比亚迪", "宁德时代"]
deleted = stocks.pop(1)
print(deleted)
print(stocks)
不传参数时,删除最后一个:
deleted = stocks.pop()
删除指定位置:
del stocks[0]
删除切片:
del stocks[1:3]
清空列表:
stocks.clear()
结果:
[]
stocks = ["贵州茅台", "比亚迪", "宁德时代"]
print(len(stocks))
结果:
3
stocks = ["贵州茅台", "比亚迪"]
print("贵州茅台" in stocks)
print("宁德时代" not in stocks)
查找元素位置:
stocks = ["贵州茅台", "比亚迪", "宁德时代"]
print(stocks.index("比亚迪"))
结果:
1
统计出现次数:
numbers = [1, 2, 2, 3, 2]
print(numbers.count(2))
结果:
3
数字升序:
numbers = [5, 2, 9, 1]
numbers.sort()
print(numbers)
结果:
[1, 2, 5, 9]
降序:
numbers.sort(reverse=True)
sort() 会修改原列表。
如果不想修改原列表,可以使用 sorted():
numbers = [5, 2, 9, 1]
new_numbers = sorted(numbers)
print(numbers)
print(new_numbers)
stocks = [
{"name": "贵州茅台", "price": 1500},
{"name": "比亚迪", "price": 300},
{"name": "中国平安", "price": 50},
]
按价格升序:
stocks.sort(key=lambda stock: stock["price"])
按价格降序:
stocks.sort(
key=lambda stock: stock["price"],
reverse=True,
)
也可以使用 sorted():
new_stocks = sorted(
stocks,
key=lambda stock: stock["price"],
reverse=True,
)
numbers = [1, 2, 3]
numbers.reverse()
print(numbers)
也可以使用切片:
new_numbers = numbers[::-1]
区别:
reverse()修改原列表[::-1]创建新列表
stocks = ["贵州茅台", "比亚迪", "宁德时代"]
for stock in stocks:
print(stock)
获取索引和值:
for index, stock in enumerate(stocks):
print(index, stock)
从 1 开始编号:
for index, stock in enumerate(stocks, start=1):
print(index, stock)
普通写法:
squares = []
for number in range(1, 6):
squares.append(number ** 2)
列表推导式:
squares = [
number ** 2
for number in range(1, 6)
]
结果:
[1, 4, 9, 16, 25]
带条件:
even_numbers = [
number
for number in range(1, 11)
if number % 2 == 0
]
结果:
[2, 4, 6, 8, 10]
字符串处理:
codes = [" 600519 ", " 000001 ", " 300750 "]
clean_codes = [
code.strip()
for code in codes
]
带条件过滤:
main_board_codes = [
code
for code in codes
if code.startswith(("00", "60"))
]
列表中还可以保存列表:
data = [
["600519", "贵州茅台", 1500],
["000001", "平安银行", 11],
["300750", "宁德时代", 300],
]
访问第一行:
print(data[0])
访问第一行第二列:
print(data[0][1])
结果:
贵州茅台
遍历二维列表:
for row in data:
code = row[0]
name = row[1]
price = row[2]
print(code, name, price)
也可以直接解包:
for code, name, price in data:
print(code, name, price)
直接赋值并不是复制:
a = [1, 2, 3]
b = a
b.append(4)
print(a)
结果:
[1, 2, 3, 4]
因为 a 和 b 指向同一个列表。
浅复制:
a = [1, 2, 3]
b = a.copy()
也可以:
b = a[:]
或者:
b = list(a)
修改 b 不会影响 a:
b.append(4)
print(a)
print(b)
当列表中还有嵌套列表时,浅复制可能不够。
a = [
[1, 2],
[3, 4],
]
b = a.copy()
b[0].append(100)
print(a)
原列表也会发生变化。
需要使用深拷贝:
from copy import deepcopy
a = [
[1, 2],
[3, 4],
]
b = deepcopy(a)
b[0].append(100)
print(a)
print(b)
元组和列表类似,但是元组创建后不能修改。
特点:
- 有顺序
- 不可修改
- 可以重复
- 可以保存不同类型
创建元组:
stock = ("600519", "贵州茅台", 1500.0)
numbers = (10, 20, 30)
也可以省略括号:
numbers = 10, 20, 30
空元组:
numbers = ()
单元素元组必须保留逗号:
value = (10,)
下面不是元组:
value = (10)
查看类型:
print(type((10,)))
print(type((10)))
结果:
<class 'tuple'>
<class 'int'>
stock = ("600519", "贵州茅台", 1500.0)
print(stock[0])
print(stock[-1])
元组也支持切片:
print(stock[:2])
错误:
stock[1] = "五粮液"
会出现:
TypeError
如果需要修改,可以转换为列表:
stock = ("600519", "贵州茅台", 1500.0)
stock_list = list(stock)
stock_list[1] = "五粮液"
stock = tuple(stock_list)
stock = ("600519", "贵州茅台", 1500.0)
code, name, price = stock
print(code)
print(name)
print(price)
变量数量必须与元素数量一致。
numbers = (1, 2, 3, 4, 5)
first, *middle, last = numbers
print(first)
print(middle)
print(last)
结果:
1
[2, 3, 4]
5
注意,带星号的变量得到的是列表。
传统写法:
a = 10
b = 20
temp = a
a = b
b = temp
Python 可以直接写:
a, b = b, a
本质上使用了元组打包和解包。
元组适合保存不应被修改的数据。
例如坐标:
point = (120.5, 30.2)
RGB 颜色:
color = (255, 128, 0)
数据库一行查询结果:
row = ("600519", "贵州茅台", 1500.0)
函数返回多个值:
def get_stock() -> tuple[str, str, float]:
return "600519", "贵州茅台", 1500.0
调用:
code, name, price = get_stock()
字典使用键值对保存数据。
例如:
stock = {
"code": "600519",
"name": "贵州茅台",
"price": 1500.0,
}
其中:
"code"是键"600519"是值"name"是键"贵州茅台"是值
字典非常适合描述一个对象。
空字典:
stock = {}
也可以:
stock = dict()
创建有数据的字典:
stock = {
"code": "600519",
"name": "贵州茅台",
"price": 1500.0,
}
也可以使用 dict():
stock = dict(
code="600519",
name="贵州茅台",
price=1500.0,
)
这种写法要求键是合法变量名。
使用中括号:
print(stock["name"])
结果:
贵州茅台
如果键不存在,会报错:
print(stock["industry"])
更安全的方式是 get():
print(stock.get("industry"))
键不存在时返回 None。
设置默认值:
industry = stock.get("industry", "未知行业")
print(industry)
stock["industry"] = "白酒"
此时字典:
{
"code": "600519",
"name": "贵州茅台",
"price": 1500.0,
"industry": "白酒",
}
stock["price"] = 1520.0
如果键已经存在,就是修改。
如果键不存在,就是新增。
stock.update({
"price": 1520.0,
"industry": "白酒",
})
也可以:
stock.update(
price=1520.0,
industry="白酒",
)
price = stock.pop("price")
print(price)
如果键可能不存在:
price = stock.pop("price", None)
del stock["industry"]
如果键不存在会报错。
删除最后添加的键值对:
key, value = stock.popitem()
print(key, value)
清空字典:
stock.clear()
if "code" in stock:
print(stock["code"])
判断不存在:
if "industry" not in stock:
print("没有行业信息")
in 默认判断的是键,而不是值。
判断值:
print("贵州茅台" in stock.values())
print(stock.keys())
转换为列表:
keys = list(stock.keys())
print(stock.values())
转换为列表:
values = list(stock.values())
print(stock.items())
结果类似:
dict_items([
("code", "600519"),
("name", "贵州茅台"),
("price", 1500.0),
])
遍历键:
for key in stock:
print(key)
也可以:
for key in stock.keys():
print(key)
遍历值:
for value in stock.values():
print(value)
同时遍历键和值:
for key, value in stock.items():
print(key, value)
字典的值也可以是字典:
stock = {
"code": "600519",
"name": "贵州茅台",
"financial": {
"revenue": 1500,
"profit": 700,
},
}
获取嵌套数据:
print(stock["financial"]["profit"])
结果:
700
更安全的写法:
financial = stock.get("financial", {})
profit = financial.get("profit", 0)
print(profit)
实际项目中经常使用列表保存多个字典。
stocks = [
{
"code": "600519",
"name": "贵州茅台",
"price": 1500.0,
},
{
"code": "000001",
"name": "平安银行",
"price": 11.5,
},
{
"code": "300750",
"name": "宁德时代",
"price": 300.0,
},
]
遍历:
for stock in stocks:
code = stock["code"]
name = stock["name"]
price = stock["price"]
print(code, name, price)
筛选主板股票:
main_board_stocks = [
stock
for stock in stocks
if stock["code"].startswith(("00", "60"))
]
筛选价格大于 100:
expensive_stocks = [
stock
for stock in stocks
if stock["price"] > 100
]
普通写法:
squares = {}
for number in range(1, 6):
squares[number] = number ** 2
字典推导式:
squares = {
number: number ** 2
for number in range(1, 6)
}
结果:
{
1: 1,
2: 4,
3: 9,
4: 16,
5: 25,
}
交换键和值:
stock_codes = {
"贵州茅台": "600519",
"平安银行": "000001",
}
code_names = {
code: name
for name, code in stock_codes.items()
}
当键不存在时设置默认值:
stock = {
"code": "600519",
}
stock.setdefault("name", "未知")
如果键不存在,就添加:
{
"code": "600519",
"name": "未知",
}
如果键已经存在,不会覆盖:
stock.setdefault("code", "000001")
code 仍然是 "600519"。
统计字符出现次数:
text = "hello"
counts = {}
for char in text:
counts[char] = counts.get(char, 0) + 1
print(counts)
结果:
{
"h": 1,
"e": 1,
"l": 2,
"o": 1,
}
统计股票代码前两位:
codes = [
"600519",
"000001",
"002594",
"300750",
"603259",
"000858",
]
prefix_counts = {}
for code in codes:
prefix = code[:2]
prefix_counts[prefix] = prefix_counts.get(prefix, 0) + 1
print(prefix_counts)
集合用于保存不重复的数据。
特点:
- 元素不重复
- 没有固定索引
- 可以进行交集、并集、差集运算
- 适合去重和成员判断
numbers = {1, 2, 3, 4}
重复元素会自动去除:
numbers = {1, 2, 2, 3, 3, 4}
print(numbers)
结果:
{1, 2, 3, 4}
正确:
numbers = set()
错误:
numbers = {}
{} 创建的是空字典。
codes = [
"600519",
"000001",
"600519",
"300750",
]
unique_codes = set(codes)
print(unique_codes)
如果需要列表:
unique_codes = list(set(codes))
注意,集合不保证原顺序。
如果需要保持原顺序,不建议直接使用 set()。
写法一:
codes = [
"600519",
"000001",
"600519",
"300750",
]
result = []
for code in codes:
if code not in result:
result.append(code)
print(result)
更高效的写法:
result = []
seen = set()
for code in codes:
if code in seen:
continue
seen.add(code)
result.append(code)
还可以利用字典保持顺序:
result = list(dict.fromkeys(codes))
codes = {"600519", "000001"}
codes.add("300750")
添加多个元素:
codes.update([
"002594",
"603259",
])
codes.remove("600519")
元素不存在时会报错。
codes.discard("600519")
元素不存在时不会报错。
通常在不确定元素是否存在时,优先使用 discard()。
随机删除并返回一个元素:
code = codes.pop()
因为集合无固定顺序,所以不能确定删除哪个元素。
codes.clear()
a = {"600519", "000001"}
b = {"000001", "300750"}
使用 |:
result = a | b
结果:
{"600519", "000001", "300750"}
也可以:
result = a.union(b)
找出两个集合都包含的数据:
result = a & b
结果:
{"000001"}
也可以:
result = a.intersection(b)
实际场景:
watch_list = {
"600519",
"000001",
"300750",
}
rising_stocks = {
"000001",
"300750",
"002594",
}
watched_rising_stocks = watch_list & rising_stocks
print(watched_rising_stocks)
结果:
{"000001", "300750"}
找出在 a 中但不在 b 中的数据:
result = a - b
也可以:
result = a.difference(b)
实际场景:
all_codes = {
"600519",
"000001",
"300750",
}
excluded_codes = {
"000001",
}
result = all_codes - excluded_codes
结果:
{"600519", "300750"}
找出只出现在其中一个集合中的元素:
result = a ^ b
也可以:
result = a.symmetric_difference(b)
a = {1, 2}
b = {1, 2, 3, 4}
判断 a 是否为 b 的子集:
print(a <= b)
print(a.issubset(b))
判断 b 是否为 a 的超集:
print(b >= a)
print(b.issuperset(a))
判断是否没有共同元素:
a = {1, 2}
b = {3, 4}
print(a.isdisjoint(b))
结果:
True
squares = {
number ** 2
for number in range(1, 6)
}
筛选偶数:
even_numbers = {
number
for number in range(1, 11)
if number % 2 == 0
}
理解可变和不可变,是掌握 Python 数据结构的重要基础。
创建后可以修改:
listdictset
例如:
numbers = [1, 2, 3]
numbers.append(4)
原列表被修改。
创建后不能修改:
strtupleintfloatbool
例如:
text = "Python"
text.upper()
upper() 返回新字符串,不会修改原字符串。
text = "Python"
new_text = text.upper()
print(text)
print(new_text)
结果:
Python
PYTHON
Python 变量保存的不是数据本身,而是对象的引用。
a = [1, 2, 3]
b = a
此时 a 和 b 指向同一个列表。
b.append(4)
print(a)
结果:
[1, 2, 3, 4]
可以使用 id() 查看对象标识:
print(id(a))
print(id(b))
两者相同。
如果需要复制:
b = a.copy()
判断值是否相等:
a = [1, 2, 3]
b = [1, 2, 3]
print(a == b)
结果:
True
判断是否为同一个对象:
print(a is b)
结果:
False
因为它们的内容相同,但不是同一个列表对象。
is 最常用于判断 None:
result = None
if result is None:
print("没有结果")
不推荐:
if result == None:
pass
推荐:
if result is None:
pass
text = "600519,000001,300750"
codes = text.split(",")
print(codes)
codes = ["600519", "000001", "300750"]
text = ",".join(codes)
numbers = [1, 2, 3]
result = tuple(numbers)
numbers = (1, 2, 3)
result = list(numbers)
numbers = [1, 2, 2, 3]
result = set(numbers)
适合去重。
numbers = {1, 2, 3}
result = list(numbers)
键值对列表:
items = [
("code", "600519"),
("name", "贵州茅台"),
("price", 1500.0),
]
stock = dict(items)
结果:
{
"code": "600519",
"name": "贵州茅台",
"price": 1500.0,
}
keys = ["code", "name", "price"]
values = ["600519", "贵州茅台", 1500.0]
stock = dict(zip(keys, values))
结果:
{
"code": "600519",
"name": "贵州茅台",
"price": 1500.0,
}
zip() 用于同时组合多个可迭代对象。
codes = [
"600519",
"000001",
"300750",
]
names = [
"贵州茅台",
"平安银行",
"宁德时代",
]
同时遍历:
for code, name in zip(codes, names):
print(code, name)
转换为字典:
stocks = dict(zip(codes, names))
结果:
{
"600519": "贵州茅台",
"000001": "平安银行",
"300750": "宁德时代",
}
注意,zip() 会以最短的数据长度为准。
enumerate() 用于同时获取索引和值。
stocks = [
"贵州茅台",
"平安银行",
"宁德时代",
]
for index, stock in enumerate(stocks):
print(index, stock)
结果:
0 贵州茅台
1 平安银行
2 宁德时代
从 1 开始:
for index, stock in enumerate(stocks, start=1):
print(index, stock)
结果:
1 贵州茅台
2 平安银行
3 宁德时代
获取元素数量:
print(len([1, 2, 3]))
print(len({"a": 1, "b": 2}))
print(len("Python"))
numbers = [10, 5, 30, 8]
print(max(numbers))
print(min(numbers))
字典列表中获取价格最高的股票:
stocks = [
{"name": "贵州茅台", "price": 1500},
{"name": "平安银行", "price": 11},
{"name": "宁德时代", "price": 300},
]
highest_stock = max(
stocks,
key=lambda stock: stock["price"],
)
print(highest_stock)
numbers = [10, 20, 30]
print(sum(numbers))
计算股票总市值:
stocks = [
{"name": "A", "market_value": 100},
{"name": "B", "market_value": 200},
{"name": "C", "market_value": 300},
]
total_market_value = sum(
stock["market_value"]
for stock in stocks
)
numbers = [5, 2, 9, 1]
new_numbers = sorted(numbers)
按字符串长度排序:
names = [
"贵州茅台",
"平安银行",
"工业富联",
]
result = sorted(names, key=len)
只要有一个元素为真,就返回 True:
results = [False, False, True]
print(any(results))
判断是否有主板代码:
codes = ["300750", "688981", "600519"]
has_main_board = any(
code.startswith(("00", "60"))
for code in codes
)
print(has_main_board)
所有元素都为真,才返回 True:
results = [True, True, True]
print(all(results))
判断所有代码是否合法:
codes = ["600519", "000001", "300750"]
all_valid = all(
len(code) == 6 and code.isdigit()
for code in codes
)
print(all_valid)
适合保存文本:
name = "贵州茅台"
code = "600519"
股票代码虽然全是数字,但应该使用字符串。
因为:
code = "000001"
如果使用整数:
code = 1
前面的零会丢失。
适合保存一组有顺序的数据:
codes = [
"600519",
"000001",
"300750",
]
需要:
- 保持顺序
- 允许重复
- 经常添加、删除、修改
使用列表。
适合保存不应该修改的数据:
point = (120.5, 30.2)
或者函数返回固定结构:
def get_user():
return "张三", 25
适合描述一个对象:
stock = {
"code": "600519",
"name": "贵州茅台",
"price": 1500.0,
}
当数据具有明确字段名称时,优先考虑字典。
适合:
- 去重
- 快速判断元素是否存在
- 集合运算
excluded_codes = {
"600519",
"000001",
}
判断代码是否排除:
if code in excluded_codes:
print("排除该股票")
集合成员判断通常比列表更高效。
原始数据:
stocks = [
{
"code": " 600519 ",
"name": "贵州茅台",
"price": 1500.0,
"industry": "白酒",
},
{
"code": "000001",
"name": "平安银行",
"price": 11.5,
"industry": "银行",
},
{
"code": "600519",
"name": "贵州茅台",
"price": 1500.0,
"industry": "白酒",
},
{
"code": "300750",
"name": "宁德时代",
"price": 300.0,
"industry": "电池",
},
]
需求:
- 清理代码两端空格。
- 删除重复股票。
- 筛选主板股票。
- 按价格降序排列。
- 按行业统计数量。
完整代码:
stocks = [
{
"code": " 600519 ",
"name": "贵州茅台",
"price": 1500.0,
"industry": "白酒",
},
{
"code": "000001",
"name": "平安银行",
"price": 11.5,
"industry": "银行",
},
{
"code": "600519",
"name": "贵州茅台",
"price": 1500.0,
"industry": "白酒",
},
{
"code": "300750",
"name": "宁德时代",
"price": 300.0,
"industry": "电池",
},
]
清理代码:
for stock in stocks:
stock["code"] = stock["code"].strip()
按照代码去重:
unique_stocks = []
seen_codes = set()
for stock in stocks:
code = stock["code"]
if code in seen_codes:
continue
seen_codes.add(code)
unique_stocks.append(stock)
筛选主板股票:
main_board_stocks = [
stock
for stock in unique_stocks
if stock["code"].startswith(("00", "60"))
]
按照价格降序:
main_board_stocks.sort(
key=lambda stock: stock["price"],
reverse=True,
)
统计行业数量:
industry_counts = {}
for stock in unique_stocks:
industry = stock["industry"]
industry_counts[industry] = (
industry_counts.get(industry, 0) + 1
)
输出结果:
for stock in main_board_stocks:
print(
stock["code"],
stock["name"],
stock["price"],
)
print(industry_counts)
完整函数:
def process_stocks(
stocks: list[dict[str, object]],
) -> tuple[
list[dict[str, object]],
dict[str, int],
]:
unique_stocks: list[dict[str, object]] = []
seen_codes: set[str] = set()
for stock in stocks:
code = str(stock.get("code", "")).strip()
stock["code"] = code
if code in seen_codes:
continue
seen_codes.add(code)
unique_stocks.append(stock)
main_board_stocks = [
stock
for stock in unique_stocks
if str(stock["code"]).startswith(("00", "60"))
]
main_board_stocks.sort(
key=lambda stock: float(stock.get("price", 0)),
reverse=True,
)
industry_counts: dict[str, int] = {}
for stock in unique_stocks:
industry = str(
stock.get("industry", "未知行业")
)
industry_counts[industry] = (
industry_counts.get(industry, 0) + 1
)
return main_board_stocks, industry_counts
调用:
main_board_stocks, industry_counts = (
process_stocks(stocks)
)
print(main_board_stocks)
print(industry_counts)
不推荐:
numbers = [1, 2, 3, 4, 5]
for number in numbers:
if number % 2 == 0:
numbers.remove(number)
遍历过程中修改列表,容易漏掉元素。
推荐创建新列表:
numbers = [1, 2, 3, 4, 5]
numbers = [
number
for number in numbers
if number % 2 != 0
]
容易报错:
price = stock["price"]
更安全:
price = stock.get("price", 0)
但如果字段必须存在,使用中括号反而更合适,因为可以及时暴露数据问题。
numbers = [1, 2]
使用 append():
numbers.append([3, 4])
结果:
[1, 2, [3, 4]]
使用 extend():
numbers = [1, 2]
numbers.extend([3, 4])
结果:
[1, 2, 3, 4]
remove() 按值删除:
numbers.remove(20)
pop() 按索引删除:
numbers.pop(1)
错误:
data = {}
这是字典。
正确:
data = set()
不推荐:
def add_item(
item: str,
items: list[str] = [],
) -> list[str]:
items.append(item)
return items
默认列表会被多次调用共享。
推荐:
def add_item(
item: str,
items: list[str] | None = None,
) -> list[str]:
if items is None:
items = []
items.append(item)
return items
给定列表:
numbers = [1, 2, 2, 3, 4, 4, 5]
删除重复元素并保持原顺序。
参考答案:
result = list(dict.fromkeys(numbers))
print(result)
给定股票代码:
codes = [
"600519",
"000001",
"300750",
"603259",
"002594",
]
筛选以 00 或 60 开头的代码。
参考答案:
result = [
code
for code in codes
if code.startswith(("00", "60"))
]
print(result)
统计列表中每个行业出现次数:
industries = [
"银行",
"白酒",
"银行",
"半导体",
"白酒",
"银行",
]
参考答案:
counts = {}
for industry in industries:
counts[industry] = counts.get(industry, 0) + 1
print(counts)
给定股票列表:
stocks = [
{"name": "贵州茅台", "price": 1500},
{"name": "平安银行", "price": 11},
{"name": "宁德时代", "price": 300},
]
找出价格最高的股票。
参考答案:
highest_stock = max(
stocks,
key=lambda stock: stock["price"],
)
print(highest_stock)
找出两个股票列表中共同出现的代码。
list_a = [
"600519",
"000001",
"300750",
]
list_b = [
"000001",
"300750",
"002594",
]
参考答案:
result = set(list_a) & set(list_b)
print(result)
将下面两个列表组合成字典:
codes = [
"600519",
"000001",
]
names = [
"贵州茅台",
"平安银行",
]
参考答案:
stocks = dict(zip(codes, names))
print(stocks)
将列表中的股票按照价格降序排列:
stocks = [
{"name": "A公司", "price": 20},
{"name": "B公司", "price": 50},
{"name": "C公司", "price": 10},
]
参考答案:
stocks.sort(
key=lambda stock: stock["price"],
reverse=True,
)
print(stocks)
字符串:
text = "Python"
适合保存文本,不能直接修改。
列表:
items = [1, 2, 3]
适合保存有顺序、需要修改的数据。
元组:
point = (10, 20)
适合保存固定、不应修改的数据。
字典:
user = {
"name": "张三",
"age": 25,
}
适合保存具有字段名称的对象数据。
集合:
codes = {
"600519",
"000001",
}
适合去重、成员判断和集合运算。
选择数据结构时,可以先问自己四个问题:
数据是否需要保持顺序?
数据是否允许重复?
数据是否需要修改?
数据是否具有明确的字段名称?
常见选择:
| 数据类型 | 数据结构 |
|---|---|
| 一段文本 | 字符串 |
| 一组有序数据 | 列表 |
| 固定不变的一组数据 | 元组 |
| 一个具有多个属性的对象 | 字典 |
| 一组不能重复的数据 | 集合 |
| 多个对象 | 列表 + 字典 |
实际 Python 项目中,最常见的组合是:
list[dict]
例如:
stocks = [
{
"code": "600519",
"name": "贵州茅台",
},
{
"code": "000001",
"name": "平安银行",
},
]
掌握字符串、列表、字典和集合,已经可以处理大部分日常数据整理任务。