我相信事在人为,人定胜天,现在还是在基础语法上面打转,还是会提出一些很低级的很基础的问题,不要着急,波浪式前进、螺旋式上升的过程吧,虽然现在的确是很绝望吧......
今天要做一个练习:编写猜数字游戏(随机生成 1-100 的数字,用户猜测)
1 python的f-strings格式化字符串字面量,对比一下java里面的printf
其实我不是很明白,这是我的个人理解:
py里面print(f"",{}),f表示格式化输出,{}类似于一种占位符,{变量名称}
ai解答:
是的,你理解得很正确。
在 Python 中,f
开头的字符串(即 f-string)是一种字符串格式化方法,它让字符串插值变得更简洁易读。在 f""
中,花括号 {}
用于嵌入表达式或变量,Python 会在运行时将其替换为实际的值。
简单示例:
python
运行
name = "Alice"
age = 30# 使用 f-string 格式化输出
print(f"我的名字是 {name},今年 {age} 岁。")
# 输出:我的名字是 Alice,今年 30 岁。# 可以直接在 {} 中使用表达式
print(f"明年我将是 {age + 1} 岁。")
# 输出:明年我将是 31 岁。
更灵活的用法:
-
调用函数:
python
运行
def double(x):return x * 2num = 5 print(f"5 的两倍是 {double(num)}。") # 输出:5 的两倍是 10。
-
格式化数字:
python
运行
pi = 3.1415926 print(f"π 约等于 {pi:.2f}。") # 保留两位小数 # 输出:π 约等于 3.14。price = 99.9 print(f"价格是 ${price:.2f}。") # 强制保留两位小数 # 输出:价格是 $99.90。
-
对齐和填充:
python
运行
width = 10 print(f"{'左对齐':<{width}}") # 左对齐 print(f"{'右对齐':>{width}}") # 右对齐 print(f"{'居中':^{width}}") # 居中
输出:
plaintext
左对齐 右对齐居中
-
访问对象属性或列表元素:
python
运行
person = {"name": "Bob", "city": "Beijing"} print(f"{person['name']} 住在 {person['city']}。") # 输出:Bob 住在 Beijing。numbers = [10, 20, 30] print(f"第二个数是 {numbers[1]}。") # 输出:第二个数是 20。
注意事项:
-
引号冲突:如果字符串中需要使用与
f""
相同的引号,需用反斜杠转义或嵌套不同类型的引号。例如:python
运行
print(f"他说:\"你好!\"") # 使用转义 print(f'他说:"你好!"') # 嵌套单引号
-
表达式复杂时:虽然可以在
{}
中写复杂表达式,但建议保持简洁,否则会降低可读性。例如:python
运行
# 不推荐(太复杂) print(f"结果是 {((x+y)*z)/w:.2f}")# 推荐(先计算,再使用变量) result = ((x+y)*z)/w print(f"结果是 {result:.2f}")
f-string 是 Python 3.6+ 引入的特性,它比传统的 %
格式化和 str.format()
更直观、高效,是目前最推荐的字符串格式化方式。
在 Python 中,f-strings(格式化字符串字面量)提供了一种简洁、直观且高效的方式来嵌入表达式或变量到字符串中。这种设计主要出于以下几个原因:
1. 语法简洁性
- Python 的哲学是 "用一种方法,最好只有一种方法来做一件事",但字符串格式化在历史上有多种方式(
%
格式化、str.format()
、f-strings)。f-strings 被设计为最直观的方式。 - 示例对比:
python
运行
# 传统方式(% 格式化) name = "Alice" print("Hello, %s!" % name)# 现代方式(f-string) print(f"Hello, {name}!")
2. 动态表达式支持
- 在
{}
中可以直接使用变量、函数调用、甚至复杂表达式,无需预先计算:python
运行
def get_name():return "Bob"print(f"Hello, {get_name().upper()}!") # 输出:Hello, BOB!
3. 性能优势
- f-strings 在运行时直接求值并替换,比
%
格式化和str.format()
更快。例如:python
运行
# 更快的内联求值 x = 10 print(f"平方:{x**2}") # 直接计算 x²
4. 可读性提升
- 变量名直接出现在字符串中,使代码更易理解:
python
运行
width = 10 height = 5 print(f"面积 = {width} × {height} = {width * height}") # 输出:面积 = 10 × 5 = 50
5. 与 Java 的 printf
的对比
Java 的 printf
是基于 C 语言的格式化风格,使用占位符(如 %s
、%d
),而 Python 的 f-strings 更灵活:
特性 | Python f-strings | Java printf |
---|---|---|
语法 | f"文本 {表达式}" | "文本 %s %d" % (变量, 值) |
动态表达式 | 支持直接嵌入函数调用、计算等 | 需要预先计算所有值 |
变量可见性 | 直接使用变量名,如 {name} | 依赖位置参数(%1$s 、%2$d ) |
类型安全 | 自动处理类型转换 | 需要显式指定类型(%s 、%d ) |
性能 | 运行时直接替换,效率高 | 依赖字符串解析,相对较慢 |
6. Python 的设计哲学
Python 强调代码的可读性和简洁性,f-strings 符合这一哲学:
- 更少的样板代码:不需要像 Java 那样频繁使用
+
拼接字符串。 - 更 Pythonic:与列表推导式、生成器表达式等特性一致,用简洁的语法解决常见需求。
7. 演进历史
Python 早期只有 %
格式化(类似 C 语言),后来引入 str.format()
提升灵活性,但 f-strings(Python 3.6+)进一步简化了语法。例如:
python
运行
# 旧方式(Python 2/3 早期)
print("姓名:{},年龄:{}".format("Charlie", 25))# 新方式(f-string)
print(f"姓名:{'Charlie'},年龄:{25}")
总结
Python 的 f-strings 是为了提供一种更直观、高效且符合语言哲学的字符串格式化方式,相比 Java 的 printf
,它更灵活、更具表达力,且与 Python 的动态特性结合得更好。
2 异常处理和文件读取练习
写到这个地方写不下去了,不知道怎么统计单词
# 下面是一个关于 Python 异常处理的练习题,你可以尝试完成它。
# 练习题:文件内容分析器
# 要求:
# 编写一个 Python 程序,实现以下功能:
# 提示用户输入一个文件路径。
# 尝试读取该文件的内容。
# 统计文件中的行数、单词数(以空格分隔)和字符数(包括空格和换行符)。
# 打印统计结果。
# 需要处理的异常情况:
# 文件不存在。
# 文件没有读取权限。
# 文件为空(此时输出统计结果为全零)。
# 用户输入无效路径(例如包含非法字符)。
# 示例输出:
# plaintext
# 请输入文件路径: test.txt
# 文件统计结果:
# - 行数: 3
# - 单词数: 12
# - 字符数: 56
#
# 异常处理示例:
# plaintext
# 请输入文件路径: /nonexistent/file.txt
# 错误:文件不存在!
#
# plaintext
# 请输入文件路径: /etc/shadow
# 错误:没有读取该文件的权限!
#
# 你可以将答案写在下面,我会为你检查。location = input("请输入文件路径:")
try:f = open(location + ".txt", "w", encoding="utf-8")
except FileNotFoundError:print("找不到文件")
except FileExistsError:print("文件不存在")
except PermissionError:print("没有读取权限")
else:f.readlines()f.close()
ai给的修改后的正确代码:
# 获取用户输入的文件路径
location = input("请输入文件路径:")try:# 尝试以只读模式打开文件with open(location, "r", encoding="utf-8") as file:# 读取全部内容content = file.read()# 统计行数lines = content.count('\n') + 1 if content else 0# 统计单词数(以空格分隔)words = len(content.split()) if content else 0# 统计字符数(包括空格和换行符)characters = len(content)# 打印统计结果print("文件统计结果:")print(f"- 行数: {lines}")print(f"- 单词数: {words}")print(f"- 字符数: {characters}")except FileNotFoundError:print("错误:文件不存在!")
except PermissionError:print("错误:没有读取该文件的权限!")
except IsADirectoryError:print("错误:输入的是一个目录,请提供有效的文件路径!")
except UnicodeDecodeError:print("错误:文件编码不是UTF-8,请提供UTF-8编码的文件!")
except Exception as e:print(f"错误:发生未知错误 - {e}")
原先代码存在的问题:
- 使用了写入模式打开文件:
open(location + ".txt", "w")
这会创建 / 覆盖文件 - 异常处理逻辑有些混乱:
FileExistsError
不应该用于检查文件是否存在 - 没有实现统计行数、单词数和字符数的逻辑
3 python中的with语句
with
语句是 Python 中用于简化资源管理的语法结构,它通过上下文管理器(Context Manager)自动处理资源的获取和释放,确保无论代码块是否正常执行完毕,资源都能被正确清理。这种模式不仅让代码更简洁,还能避免因疏忽导致的资源泄漏(如文件未关闭、网络连接未释放等)。
基本语法
python
运行
with expression [as variable]:# 代码块
expression
:返回一个上下文管理器对象(如open()
返回文件对象)。as variable
(可选):将上下文管理器的返回值赋值给变量。
核心机制:上下文管理器
with
语句依赖上下文管理器,它是实现了 __enter__()
和 __exit__()
方法的对象:
__enter__()
:在进入with
代码块前调用,返回资源对象(如文件句柄)。__exit__()
:在代码块结束后(无论是否异常)自动调用,负责清理资源(如关闭文件)。
典型应用场景
1. 文件操作(最常见)
python
运行
with open('data.txt', 'r') as file:content = file.read()# 文件在代码块结束后自动关闭
- 等价于传统写法:
python
运行
file = open('data.txt', 'r') try:content = file.read() finally:file.close() # 无论是否异常,finally 确保文件关闭
2. 数据库连接
python
运行
with sqlite3.connect('example.db') as conn:cursor = conn.cursor()cursor.execute('SELECT * FROM users')# conn.commit() 或 conn.rollback() 自动调用
- 数据库连接在
with
结束时自动提交或回滚事务,并关闭连接。
3. 线程锁
python
运行
lock = threading.Lock()
with lock: # 等价于 lock.acquire() + lock.release()# 线程安全的代码...
4. 临时修改环境
python
运行
with tempfile.TemporaryDirectory() as tmpdir:# 在临时目录中操作文件# 代码块结束后,tmpdir 自动删除
自定义上下文管理器
如果你需要管理自定义资源,可以通过以下两种方式创建上下文管理器:
方式 1:类实现
python
运行
class MyResource:def __enter__(self):print("获取资源")return self # 返回资源对象def __exit__(self, exc_type, exc_val, exc_tb):print("释放资源")# 异常处理逻辑(如果需要)with MyResource() as resource:# 使用 resourcepass # 输出:获取资源 → 释放资源
方式 2:装饰器 + 生成器(更简洁)
python
运行
from contextlib import contextmanager@contextmanager
def my_context_manager():# __enter__ 逻辑resource = "初始化资源"try:yield resource # 返回资源给 with 语句finally:# __exit__ 逻辑print("清理资源")with my_context_manager() as res:print(res) # 输出:初始化资源
with
语句的优势
- 自动资源管理:避免手动调用
close()
、release()
等方法。 - 异常安全:即使代码块中抛出异常,资源也会被正确释放。
- 代码简洁:减少样板代码(如
try-finally
)。
常见内置上下文管理器
open()
:文件操作threading.Lock()
:线程锁tempfile.TemporaryFile()
:临时文件contextlib.suppress()
:抑制特定异常unittest.mock.patch()
:测试中的临时补丁
注意事项
-
变量作用域:
with
中定义的变量在代码块外仍可用,但资源可能已关闭。python
运行
with open('test.txt') as f:data = f.read() print(data) # 正常访问,但 f.closed 为 True
-
嵌套
with
语句:支持多层资源管理。python
运行
with open('input.txt') as infile, open('output.txt', 'w') as outfile:outfile.write(infile.read())
-
异常处理:
__exit__()
方法可捕获并处理异常(通过exc_type
参数判断)。
总结
with
语句通过上下文管理器实现了资源的自动获取和释放,是 Python 中优雅且安全的编程实践。常见于文件操作、数据库连接、网络会话等需要显式关闭资源的场景,能有效避免资源泄漏,提升代码可靠性。
4 python的三元表达式
Python 的三元表达式(Ternary Expression),也称为条件表达式(Conditional Expression),是一种简洁的语法结构,允许你在一行代码中根据条件选择不同的值。
它提供了一种比传统的if-else
语句更紧凑的方式来表达条件逻辑。
基本语法
python
运行
value_if_true if condition else value_if_false
执行逻辑:
- 如果
condition
为True
,表达式返回value_if_true
。 - 如果
condition
为False
,表达式返回value_if_false
。
简单示例
示例 1:比较两个数的大小
python
运行
a = 10
b = 20max_value = a if a > b else b
print(max_value) # 输出:20
示例 2:判断奇偶性
python
运行
num = 7
result = "偶数" if num % 2 == 0 else "奇数"
print(result) # 输出:奇数
与传统if-else
的对比
传统写法:
python
运行
if num % 2 == 0:result = "偶数"
else:result = "奇数"
三元表达式:
python
运行
result = "偶数" if num % 2 == 0 else "奇数"
优势:
- 代码更简洁,减少行数。
- 适合在赋值语句中直接使用,无需额外的代码块。
进阶用法
1. 嵌套三元表达式
可以在三元表达式中嵌套另一个三元表达式,但过度嵌套会降低代码可读性。
python
运行
x = 15
result = "大正数" if x > 10 else ("小正数" if x > 0 else "非正数")
print(result) # 输出:大正数
2. 与函数调用结合
python
运行
def get_name():return "Alice"def get_default():return "Guest"name = get_name() if user_logged_in else get_default()
3. 在列表推导式中使用
python
运行
numbers = [1, -2, 3, -4, 5]
abs_values = [num if num >= 0 else -num for num in numbers]
print(abs_values) # 输出:[1, 2, 3, 4, 5]
注意事项
-
避免复杂条件:如果条件或表达式过于复杂,建议使用传统的
if-else
语句,以保持代码可读性。 -
空值处理:
python
运行
# 如果 x 为 None,使用默认值 0 value = x if x is not None else 0
-
执行顺序:三元表达式是从左到右求值的,先判断
condition
,再根据结果选择返回值。
历史背景
Python 直到2.5 版本才引入三元表达式语法。在此之前,常见的替代方案是:
python
运行
# Python 2.4及之前的写法
value = (value_if_false, value_if_true)[condition]
这种写法利用了布尔值可以作为列表索引(True
为 1,False
为 0)的特性,但可读性较差。
总结
三元表达式是 Python 中一种简洁的条件赋值语法,适用于简单的条件判断场景。它能让代码更紧凑,但应避免过度使用导致代码难以理解。当逻辑较为复杂时,建议优先使用传统的if-else
语句。
lines = content.count('\n') + 1 if content else 0
#怎么理解这个三元表达式
这行代码是用于统计文本内容中的行数,它巧妙地处理了空文件和非空文件两种情况。我来详细解释一下:
代码拆解
python
运行
lines = content.count('\n') + 1 if content else 0
这行代码使用了 Python 的三元表达式(也称为条件表达式),等价于:
python
运行
if content: # 如果 content 不为空字符串lines = content.count('\n') + 1
else: # 如果 content 是空字符串(文件为空)lines = 0
核心逻辑分析
1. content.count('\n')
count()
是字符串方法,用于统计子字符串在原字符串中出现的次数。content.count('\n')
计算文本中换行符的数量。
2. 为什么要 + 1
?
- 换行符的位置:在文本中,换行符
\n
位于每行的末尾(除了最后一行)。
例如,一个包含 3 行的文件:plaintext
Line 1\n Line 2\n Line 3
这里有 2 个换行符,但实际上有 3 行。因此,行数 = 换行符数量 + 1。
3. 特殊情况:空文件
- 如果文件为空,
content
是空字符串(''
)。''.count('\n')
返回0
,但空文件的行数应为0
,而不是0 + 1 = 1
。- 因此,当
content
为空时,直接返回0
。
示例验证
例 1:3 行文本
python
运行
content = "Line 1\nLine 2\nLine 3"
print(content.count('\n')) # 输出 2
print(content.count('\n') + 1) # 输出 3(正确的行数)
例 2:1 行文本(无换行符)
python
运行
content = "Only one line"
print(content.count('\n')) # 输出 0
print(content.count('\n') + 1) # 输出 1(正确的行数)
例 3:空文件
python
运行
content = ""
print(content.count('\n')) # 输出 0
print(0 if not content else content.count('\n') + 1) # 输出 0(正确的行数)
为什么需要这个逻辑?
在处理文件时,行数的统计不能简单地依赖换行符数量:
- 最后一行无换行符:大多数文本编辑器会在文件末尾自动添加换行符,但有些不会。因此,最后一行可能没有
\n
,需要通过+ 1
补偿。 - 空文件:空文件不包含任何字符,包括换行符,因此行数应为
0
。
总结
这行代码通过以下步骤准确统计行数:
- 计算换行符数量。
- 对于非空文件,行数 = 换行符数量 + 1。
- 对于空文件,直接返回
0
。
这种方法既简洁又健壮,能够处理各种边界情况,是统计文本行数的经典实现。
5 猜数游戏
我写的真的是shit吧!!!!!我真的服了。。。
import randomprint("我们来玩猜数吧!")
ans = random.randint(1,1000)#生成随机数
num = int(input("请输入1-1000中的一个数"))
while True:if num > ans:print("猜大了")continueelif num < ans:print("猜小了")continueelse:print("答对了")break
修改第一版:
import randomprint("我们来玩猜数吧!")
ans = random.randint(1, 1000) # 生成随机数
num = int(input("请输入1-1000中的一个数:"))while True:if num > ans:print("猜大了")num = int(input("请继续输入1-1000中的一个数:"))elif num < ans:print("猜小了")num = int(input("请继续输入1-1000中的一个数:"))else:print("答对了")break # 正确结束循环的语句
修改第二版,降低重复率:
import randomprint("我们来玩猜数吧!")
ans = random.randint(1, 1000) # 生成随机数while True:num = int(input("请输入1-1000中的一个数:"))if num > ans:print("猜大了")elif num < ans:print("猜小了")else:print("答对了")break # 正确结束循环的语句
这个题目太简单了基础的不行,但是我第一次写还是漏洞百出。。。好了好了,就这样。以后可以做一点扩展。
核心就是 “生成随机数→用户输入→比较判断→循环反馈” 的流程。不过,如果想让这个小游戏更有趣或更有挑战性,可以从几个方向扩展,让它稍微复杂一点,比如:
1. 增加猜测次数限制
比如限定最多猜 10 次,超时则失败,增加紧张感:
python
运行
import randomprint("猜数游戏(最多10次机会)")
ans = random.randint(1, 100)
max_attempts = 10
attempts = 0while attempts < max_attempts:num = int(input(f"请输入1-100中的数(还剩{max_attempts - attempts}次):"))attempts += 1if num > ans:print("猜大了")elif num < ans:print("猜小了")else:print(f"恭喜!用了{attempts}次就猜对了!")break
else: # 循环正常结束(未触发break)时执行print(f"次数用完啦!正确答案是{ans}")
2. 记录历史猜测记录
显示用户之前猜过的数字,帮助分析规律:
python
运行
import randomprint("带历史记录的猜数游戏")
ans = random.randint(1, 50)
history = []while True:num = int(input("请输入1-50中的数:"))history.append(num)if num > ans:print(f"猜大了,你之前猜过:{history}")elif num < ans:print(f"猜小了,你之前猜过:{history}")else:print(f"猜对了!你的猜测记录:{history},共猜了{len(history)}次")break
3. 动态调整难度
根据用户的猜测速度调整数字范围,比如第一次猜 1-100,猜对后下次扩大到 1-200,增加可玩性:
python
运行
import randommin_num, max_num = 1, 100
rounds = 1print(f"第1轮:猜1-{max_num}之间的数")
ans = random.randint(min_num, max_num)while True:num = int(input(f"请输入{min_num}-{max_num}中的数:"))if num > ans:print("猜大了")elif num < ans:print("猜小了")else:rounds += 1min_num, max_num = 1, max_num + 100 # 每轮范围+100print(f"恭喜过关!进入第{rounds}轮,范围扩大到1-{max_num}")ans = random.randint(min_num, max_num)
这些扩展虽然不复杂,但能让简单的逻辑变得更丰富,也能练习循环、条件判断、列表等基础语法的综合运用。如果想更深入,还可以加入难度选择(简单 / 中等 / 困难)、计分系统等,甚至用 GUI 库(如 tkinter)做个可视化界面~