Python 基础:列表、字符串、字典和元组一些简单八股
1 编程之前
python的运行过程实际上是翻译一行,执行一行。安装的python实际上是python解释器,然后需要安装一个代码编辑器,比如说vscode和pycharm
python安装:https://www.python.org/downloads/
pycharm安装:https://www.jetbrains.com/pycharm/
- 命令行模式(文件模式):将代码写入一个
.py
文件中,然后通过命令行运行该文件。这种方式适合编写较长的程序,便于代码的保存和复用。 - 交互模式:通过命令行工具(如cmd)进入Python交互环境,无需创建文件即可直接运行代码。这种方式适合快速测试代码片段,但输入的指令不会被保存。
BMI(Body Mass Index,体质指数)是衡量人体胖瘦程度的一个重要指标,其计算公式为:BMI = 体重(kg)/身高(m)的平方。
user_weight = float(input("输入体重(kg):"))
user_height = float(input("请输入身高(m):"))
bmi = user_weight / (user_height ** 2)
print("您的BMI是:" + str(bmi))
if-else
是条件判断的基本结构
mood_score = int(input("pls input your score:"))
if mood_score >= 60:print("a nice day!")
elif mood_score >= 0:print("a bad day")
else:print("not a person")
在Python中,逻辑运算符的优先级顺序为:not > and > or
。这意味着在复杂的条件判断中,not
运算符的优先级最高,其次是and
,最后是or
score = 70
if not score < 60 and score > 50:print("You passed!")
2 列表基础
List是一个有序的元素集合,可以包含不同类型的元素,并且是可变的。
# 创建空列表和初始化列表
shopping_list_none = [] # 空列表
shopping_list = ["鼠标", "键盘"]# 向列表中添加元素
shopping_list.append("显示器")
print(shopping_list) # 输出:['鼠标', '键盘', '显示器']# 从列表中移除元素
shopping_list.remove("鼠标")
print(shopping_list) # 输出:['键盘', '显示器']# 向列表中添加不同类型的元素
shopping_list.append(666)
print(shopping_list) # 输出:['键盘', '显示器', 666]# 通过索引访问列表中的元素
print(shopping_list[0]) # 输出:键盘
2.1列表的数学操作
除了基本的添加和移除操作,列表还支持以下数学操作:
-
最大值和最小值:使用
max()
和min()
函数获取列表的最大值和最小值。nums1 = [1, 4, 5, 6, 9, 2] print(max(nums1)) # 输出:9 print(min(nums1)) # 输出:1
-
排序:使用
sorted()
函数对列表进行排序,返回一个新的排序后的列表。print(sorted(nums1)) # 输出:[1, 2, 4, 5, 6, 9]
-
列表推导式:使用列表推导式可以快速生成新的列表。
squares = [x**2 for x in nums1] print(squares) # 输出:[1, 16, 25, 36, 81, 4]
-
列表的切片:通过切片可以获取列表的一部分。
print(nums1[1:3]) # 输出:[4, 5] print(nums1[:3]) # 输出:[1, 4, 5] print(nums1[3:]) # 输出:[6, 9, 2]
-
列表的长度:使用
len()
函数获取列表的长度。print(len(nums1)) # 输出:6
-
列表的反转:使用
reverse()
方法反转列表。nums1.reverse() print(nums1) # 输出:[2, 9, 6, 5, 4, 1]
-
列表的插入:使用
insert()
方法在指定位置插入元素。nums1.insert(2, 10) print(nums1) # 输出:[2, 9, 10, 6, 5, 4, 1]
-
列表的删除:使用
del
语句删除指定位置的元素。del nums1[2] print(nums1) # 输出:[2, 9, 6, 5, 4, 1]
-
列表的清空:使用
clear()
方法清空列表。nums1.clear() print(nums1) # 输出:[]
2.2 列表的高级操作
列表的复制
-
浅拷贝:使用
copy()
方法或切片[:]
进行浅拷贝。original_list = [1, 2, [3, 4]] copied_list = original_list.copy() copied_list[2][0] = 5 print(original_list) # 输出:[1, 2, [5, 4]] print(copied_list) # 输出:[1, 2, [5, 4]]
-
深拷贝:使用
copy
模块的deepcopy()
方法进行深拷贝。import copy original_list = [1, 2, [3, 4]] deep_copied_list = copy.deepcopy(original_list) deep_copied_list[2][0] = 5 print(original_list) # 输出:[1, 2, [3, 4]] print(deep_copied_list) # 输出:[1, 2, [5, 4]]
列表的合并
-
使用
+
运算符:将两个列表合并成一个新的列表。list1 = [1, 2, 3] list2 = [4, 5, 6] combined_list = list1 + list2 print(combined_list) # 输出:[1, 2, 3, 4, 5, 6]
-
使用
extend()
方法:将一个列表的元素添加到另一个列表中。list1 = [1, 2, 3] list2 = [4, 5, 6] list1.extend(list2) print(list1) # 输出:[1, 2, 3, 4, 5, 6]
3 字符串
String是一串字符的集合。字符串是不可变的,这意味着一旦创建,就不能直接修改。
s = "Hello"
print(s.upper()) # 将字符串转换为大写:HELLO
print(s) # 原字符串不变:Hello# 如果需要修改字符串,可以重新赋值
s = s.upper()
print(s) # 输出:HELLO
字符串的连接
-
使用
+
运算符:将多个字符串连接成一个新的字符串。greeting = "Hello" name = "Alice" message = greeting + ", " + name + "!" print(message) # 输出:Hello, Alice!
-
使用
join()
方法:将列表中的字符串元素连接成一个新的字符串。words = ["Hello", "Alice", "How", "are", "you"] sentence = " ".join(words) print(sentence) # 输出:Hello Alice How are you
字符串的分割
- 使用
split()
方法:将字符串分割成一个列表。sentence = "Hello Alice How are you" words = sentence.split() print(words) # 输出:['Hello', 'Alice', 'How', 'are', 'you']
字符串的查找和替换
-
使用
find()
方法:查找子字符串的索引位置。sentence = "Hello Alice How are you" print(sentence.find("Alice")) # 输出:6
-
使用
replace()
方法:替换字符串中的子字符串。sentence = "Hello Alice How are you" new_sentence = sentence.replace("Alice", "Bob") print(new_sentence) # 输出:Hello Bob How are you
字符串的格式化
-
使用
format()
方法:格式化字符串。greeting = "Hello" name = "Alice" message = "{} {}, how are you?".format(greeting, name) print(message) # 输出:Hello Alice, how are you?
-
使用f-string:从Python 3.6开始,可以使用f-string进行更简洁的格式化。
greeting = "Hello" name = "Alice" message = f"{greeting} {name}, how are you?" print(message) # 输出:Hello Alice, how are you?
好的 👍 我来帮你写一篇结构清晰、适合博客发布的 Python 字典(dict) 技术文章。
4. 字典
字典(dict) 是最常用的数据结构之一。它以 键值对(key-value pair) 的形式存储数据,类似现实生活中的“查字典”操作——通过关键字快速找到对应的值。字典是一种 无序、可变、以键值对存储的数据结构。
my_dict = {"name": "Alice","age": 25,"city": "Beijing"
}
"name"
,"age"
,"city"
是 键(key)"Alice"
,25
,"Beijing"
是 值(value)
- 键必须唯一,不能重复;
- 键必须是 不可变对象(如字符串、数字、元组);
- 值可以是任意对象(包括列表、字典、函数等)。
4.1 字典的常见操作
1. 创建字典
# 方式一:花括号字面量
person = {"name": "Tom", "age": 18}# 方式二:dict() 构造函数
person = dict(name="Tom", age=18)# 方式三:通过键值对序列
person = dict([("name", "Tom"), ("age", 18)])
2. 访问字典
person = {"name": "Tom", "age": 18}print(person["name"]) # 直接访问,输出 Tom
print(person.get("age")) # 推荐方式,输出 18
print(person.get("gender", "unknown")) # 不存在时返回默认值
⚠️ 如果直接用 person["gender"]
,而 key 不存在,会抛出 KeyError
;所以更推荐 dict.get()
。
3. 修改与新增
person["age"] = 20 # 修改
person["city"] = "Beijing" # 新增
4. 删除元素
person.pop("age") # 删除指定键,返回对应的值
del person["city"] # 删除键值对
person.clear() # 清空字典
5. 遍历字典
person = {"name": "Tom", "age": 18, "city": "Beijing"}for key in person: print(key, person[key]) # 遍历键for key, value in person.items():print(key, value) # 遍历键值对print(person.keys()) # 获取所有键
print(person.values()) # 获取所有值
4.2 字典推导式
字典推导式能快速构造字典,常用于数据转换。
# 例1:生成平方表
squares = {x: x**2 for x in range(5)}
print(squares) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}# 例2:翻转键值
original = {"a": 1, "b": 2}
flipped = {v: k for k, v in original.items()}
print(flipped) # {1: 'a', 2: 'b'}
数据映射:如姓名 -> 电话号码
phonebook = {"Tom": "123456", "Alice": "987654"}
频率统计
text = "hello world"
counter = {}
for char in text:counter[char] = counter.get(char, 0) + 1
print(counter) # {'h':1, 'e':1, 'l':3, ...}
4.3 进阶
1. 字典是哈希表实现的
字典的键必须是 可哈希对象(不可变类型),例如 int
、str
、tuple
。如果尝试使用可变对象(如 list
、dict
)作为键,会报错。
# 合法键
my_dict = {1: "数字键","key": "字符串键",(1, 2): "元组键"
}print(my_dict[(1, 2)]) # 输出:元组键# 非法键(会报错 TypeError: unhashable type: 'list')
try:bad_dict = {[1, 2]: "列表键"}
except TypeError as e:print("错误:", e)
2. 字典的有序性(Python 3.7+)
在 Python 3.7 之后,字典会保持插入顺序。
data = {}
data["first"] = 1
data["second"] = 2
data["third"] = 3print(data)
# 输出:{'first': 1, 'second': 2, 'third': 3}# 遍历顺序与插入顺序一致
for key in data:print(key)
# 输出:
# first
# second
# third
3. 嵌套字典
字典的值本身也可以是字典,常用于存储结构化数据。
students = {"Tom": {"age": 18, "score": 90},"Alice": {"age": 20, "score": 95}
}print(students["Tom"]["score"]) # 90# 遍历嵌套字典
for name, info in students.items():print(f"{name} 年龄:{info['age']} 分数:{info['score']}")# 输出:
# Tom 年龄:18 分数:90
# Alice 年龄:20 分数:95
4. 使用字典实现简单的缓存
字典可以作为缓存容器,用于存储已经计算过的结果,提高效率。
# 斐波那契函数带缓存
fib_cache = {}def fib(n):if n in fib_cache:return fib_cache[n]if n <= 2:value = 1else:value = fib(n - 1) + fib(n - 2)fib_cache[n] = valuereturn valueprint(fib(10)) # 55
print(fib_cache) # 打印缓存内容
好问题 👌
其实 tuple(元组) 的内容比刚才我写的要多一些。上面只是为了引出“为什么字典 key 要用 tuple 而不是 list”做的简化版。
如果要单独写一节“元组”,可以展开讲更多内容,包括:
5 元组
5.1 元组基操
1. 元组的定义与创建
- 使用小括号
()
或tuple()
构造函数。 - 只包含一个元素时要加逗号,否则会被当作普通值。
t1 = (1, 2, 3)
t2 = ("Alice", 18, "Beijing")
t3 = (42,) # 单元素元组,必须加逗号
t4 = tuple([1, 2, 3]) # 从列表转换
2. 元组的特点
- 有序性:元素有固定顺序,可以通过索引访问。
- 不可变性:元组本身不可修改,但如果元素是可变对象(比如 list),则内部内容可以改。
- 可哈希性:只要内部元素也都是不可变的,元组就可以作为字典 key 或集合元素。
t = (1, 2, [3, 4])
# 元组不可变
# t[0] = 99 # 会报错# 但元组里的 list 可变
t[2].append(5)
print(t) # (1, 2, [3, 4, 5])
3. 元组的常见操作
t = (10, 20, 30, 40, 50)print(t[0]) # 10
print(t[-1]) # 50
print(t[1:4]) # (20, 30, 40)# 解包
a, b, c, d, e = t
print(a, e) # 10 50# 忽略部分
a, *middle, e = t
print(middle) # [20, 30, 40]# 计数和索引
print(t.count(20)) # 1
print(t.index(30)) # 2
4. 元组与不可变性带来的优势
- 更安全:数据不会被意外修改;
- 性能更优:元组通常比列表占用更少内存,访问速度更快;
- 可哈希:可以作为字典 key 和集合元素。
# 元组作为集合元素
s = {("Alice", 18), ("Tom", 20)}
print(s)
5. 实际应用场景
- 存储固定数据(如经纬度、RGB 值、日期等);
- 函数多返回值:Python 函数可以同时返回多个值,本质就是一个元组。
def get_user():return ("Alice", 18, "Beijing")name, age, city = get_user()
print(name, age, city)
-
作为字典 key:当 key 需要多个字段时,用元组保证唯一性。
- 例如“张伟 + 年龄”来区分同名的人(下面案例)。
5.2 为什么需要元组?
- 元组不可变,因此更安全,避免数据被意外修改。
- 元组可以作为字典的 键(key) 或集合的元素,而列表不行。
# 元组可以作为 key
info = {("Alice", 18): "Beijing"}
print(info[("Alice", 18)]) # 输出 Beijing# 列表不行
try:bad_info = {["Alice", 18]: "Beijing"}
except TypeError as e:print("错误:", e)
# 输出 错误: unhashable type: 'list'
原因是:字典的键必须是 可哈希对象,而可哈希对象要求内容固定。列表是可变的,不能作为键;元组是不可变的,因此可以作为键。
5.3 用元组解决“同名张伟”问题
假设我们要存储多个同名的人,比如有三个 "张伟"
,他们的年龄不同,电话也不同。如果仅用名字作为 key,会覆盖掉之前的数据。
# 错误做法:key 用名字,数据会被覆盖
phonebook = {"张伟": "123456","张伟": "654321","张伟": "987654"
}
print(phonebook)
# 只保留了最后一个:{'张伟': '987654'}
解决办法:把名字和年龄组成一个元组,作为字典的 key。
# 正确做法:使用 (姓名, 年龄) 作为 key
phonebook = {("张伟", 25): "123456",("张伟", 30): "654321",("张伟", 35): "987654"
}# 按照名字+年龄精确查找
print(phonebook[("张伟", 25)]) # 输出 123456
print(phonebook[("张伟", 30)]) # 输出 654321
这样:
("张伟", 25)
和("张伟", 30)
是不同的 key,不会互相覆盖;- 我们能根据 姓名 + 年龄 唯一确定一个人,快速查找电话。
Python八股
Q:列表 list 和元组 tuple 的区别?
A: list 是可变对象,可以修改(增删改),用 []
表示;tuple 是不可变对象,不能修改,用 ()
表示。tuple 更轻量,占用内存更少,访问速度更快,通常用来表示固定结构的数据,比如坐标点 (x, y)
。
Q:Python 的 GIL 是什么?对多线程有什么影响?
A: GIL(全局解释器锁)是 CPython 解释器内部的一个互斥锁,保证同一时刻只有一个线程在执行 Python 字节码。这导致 Python 的多线程不能真正实现 CPU 并行计算。它更适合 IO 密集型任务(比如网络请求、文件读写),因为线程在等待 IO 时 GIL 会释放;而 CPU 密集型任务更适合使用多进程(multiprocessing)。
Q:with 语句是怎么工作的?
A: with 用来简化资源管理,比如文件、锁、数据库连接。进入时会调用对象的 __enter__()
方法,退出时会自动调用对象的 __exit__()
方法,即使出错也会执行。比如:
with open("a.txt", "r") as f:data = f.read()
# 自动关闭文件,不需要 f.close()
Q:*args 和 **kwargs 是什么?
A: *args 用来接收任意数量的位置参数,函数内部会把它打包成一个 tuple;**kwargs 用来接收任意数量的关键字参数,函数内部会把它打包成一个 dict。例如:
def func(*args, **kwargs):print(args) # (1, 2, 3)print(kwargs) # {'a': 10, 'b': 20}func(1, 2, 3, a=10, b=20)
Q:init 和 new 的区别?
A: __new__
负责创建对象并返回实例,是类方法;__init__
负责初始化对象,给对象赋值属性,是实例方法。比如单例模式就常常通过重写 __new__
来控制对象的唯一性。
Q:lambda 函数是什么?怎么用?
A: lambda 是匿名函数的语法,一般用于临时、简单的函数。写法是 lambda 参数: 表达式
,例如:
f = lambda x, y: x + y
print(f(2, 3)) # 5
Q:slots 是什么?怎么用?
A: __slots__
用来限制对象的属性,只允许定义在其中的属性,从而节省内存。比如:
class Person:__slots__ = ("name", "age")p = Person()
p.name = "Tom"
p.age = 18
# p.address = "Beijing" # 会报错
Q:装饰器(Decorator)和生成器(Generator)是什么?怎么用?
A: 装饰器本质是一个函数,用来给其他函数或类添加功能,常用 @
语法。例如:
def log(func):def wrapper(*args, **kwargs):print("start")res = func(*args, **kwargs)print("end")return resreturn wrapper@log
def hello():print("hello")
hello()
生成器是使用 yield
语句的函数,它会在每次调用时返回一个值,并在下次继续运行,支持惰性计算,节省内存。例如:
def gen():for i in range(3):yield i
for x in gen():print(x) # 0, 1, 2
Q:map、filter、reduce 函数是什么?怎么用?
A: map 会对序列的每个元素应用一个函数,filter 会筛选出函数返回 True 的元素,reduce 会对序列做累计计算。reduce 需要从 functools 导入。例如:
from functools import reduce
nums = [1, 2, 3, 4]print(list(map(lambda x: x*2, nums))) # [2, 4, 6, 8]
print(list(filter(lambda x: x%2==0, nums))) # [2, 4]
print(reduce(lambda a, b: a+b, nums)) # 10
Q:深拷贝和浅拷贝怎么区分?
A: 浅拷贝只复制对象本身,但子对象还是共享引用;深拷贝会复制对象和里面的所有子对象,完全独立。例如:
import copy
a = [[1, 2], [3, 4]]
b = copy.copy(a)
b[0][0] = 99
print(a) # [[99, 2], [3, 4]] 受影响c = copy.deepcopy(a)
c[0][0] = 100
print(a) # [[99, 2], [3, 4]] 不受影响