学习日志05 python

我相信事在人为,人定胜天,现在还是在基础语法上面打转,还是会提出一些很低级的很基础的问题,不要着急,波浪式前进、螺旋式上升的过程吧,虽然现在的确是很绝望吧......

今天要做一个练习:编写猜数字游戏(随机生成 1-100 的数字,用户猜测)

1 python的f-strings格式化字符串字面量,对比一下java里面的printf

其实我不是很明白,这是我的个人理解:

py里面print(f"",{}),f表示格式化输出,{}类似于一种占位符,{变量名称}

ai解答:

是的,你理解得很正确。

在 Python 中,f 开头的字符串(即 f-string)是一种字符串格式化方法,它让字符串插值变得更简洁易读。在 f"" 中,花括号 {} 用于嵌入表达式或变量,Python 会在运行时将其替换为实际的值。

简单示例:

python

运行

python 复制代码
name = "Alice"
age = 30

# 使用 f-string 格式化输出
print(f"我的名字是 {name},今年 {age} 岁。")
# 输出:我的名字是 Alice,今年 30 岁。

# 可以直接在 {} 中使用表达式
print(f"明年我将是 {age + 1} 岁。")
# 输出:明年我将是 31 岁。

更灵活的用法:

  1. 调用函数

    python

    运行

    python 复制代码
    def double(x):
        return x * 2
    
    num = 5
    print(f"5 的两倍是 {double(num)}。")
    # 输出:5 的两倍是 10。
  2. 格式化数字

    python

    运行

    python 复制代码
    pi = 3.1415926
    print(f"π 约等于 {pi:.2f}。")  # 保留两位小数
    # 输出:π 约等于 3.14。
    
    price = 99.9
    print(f"价格是 ${price:.2f}。")  # 强制保留两位小数
    # 输出:价格是 $99.90。
  3. 对齐和填充

    python

    运行

    python 复制代码
    width = 10
    print(f"{'左对齐':<{width}}")  # 左对齐
    print(f"{'右对齐':>{width}}")  # 右对齐
    print(f"{'居中':^{width}}")    # 居中

    输出:

    plaintext

    复制代码
    左对齐       
            右对齐
       居中    
  4. 访问对象属性或列表元素

    python

    运行

    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

    运行

    python 复制代码
    print(f"他说:\"你好!\"")  # 使用转义
    print(f'他说:"你好!"')    # 嵌套单引号
  • 表达式复杂时 :虽然可以在 {} 中写复杂表达式,但建议保持简洁,否则会降低可读性。例如:

    python

    运行

    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

    运行

    python 复制代码
    # 传统方式(% 格式化)
    name = "Alice"
    print("Hello, %s!" % name)
    
    # 现代方式(f-string)
    print(f"Hello, {name}!")

2. 动态表达式支持

  • {} 中可以直接使用变量、函数调用、甚至复杂表达式,无需预先计算:

    python

    运行

    python 复制代码
    def get_name():
        return "Bob"
    
    print(f"Hello, {get_name().upper()}!")  # 输出:Hello, BOB!

3. 性能优势

  • f-strings 在运行时直接求值并替换,比 % 格式化和 str.format() 更快。例如:

    python

    运行

    python 复制代码
    # 更快的内联求值
    x = 10
    print(f"平方:{x**2}")  # 直接计算 x²

4. 可读性提升

  • 变量名直接出现在字符串中,使代码更易理解: python

    运行

    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 异常处理的练习题,你可以尝试完成它。
# 练习题:文件内容分析器
# 要求:
# 编写一个 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给的修改后的正确代码:

python 复制代码
# 获取用户输入的文件路径
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}")

原先代码存在的问题:

  1. 使用了写入模式打开文件:open(location + ".txt", "w") 这会创建 / 覆盖文件
  2. 异常处理逻辑有些混乱:FileExistsError 不应该用于检查文件是否存在
  3. 没有实现统计行数、单词数和字符数的逻辑

3 python中的with语句

with 语句是 Python 中用于简化资源管理的语法结构,它通过上下文管理器(Context Manager)自动处理资源的获取和释放,确保无论代码块是否正常执行完毕,资源都能被正确清理。这种模式不仅让代码更简洁,还能避免因疏忽导致的资源泄漏(如文件未关闭、网络连接未释放等)。

基本语法

python

运行

python 复制代码
with expression [as variable]:
    # 代码块
  • expression:返回一个上下文管理器对象(如 open() 返回文件对象)。
  • as variable(可选):将上下文管理器的返回值赋值给变量。

核心机制:上下文管理器

with 语句依赖上下文管理器,它是实现了 __enter__()__exit__() 方法的对象:

  1. __enter__() :在进入 with 代码块前调用,返回资源对象(如文件句柄)。
  2. __exit__():在代码块结束后(无论是否异常)自动调用,负责清理资源(如关闭文件)。

典型应用场景

1. 文件操作(最常见)

python

运行

python 复制代码
with open('data.txt', 'r') as file:
    content = file.read()
    # 文件在代码块结束后自动关闭
  • 等价于传统写法

    python

    运行

    python 复制代码
    file = open('data.txt', 'r')
    try:
        content = file.read()
    finally:
        file.close()  # 无论是否异常,finally 确保文件关闭
2. 数据库连接

python

运行

python 复制代码
with sqlite3.connect('example.db') as conn:
    cursor = conn.cursor()
    cursor.execute('SELECT * FROM users')
    # conn.commit() 或 conn.rollback() 自动调用
  • 数据库连接在 with 结束时自动提交或回滚事务,并关闭连接。
3. 线程锁

python

运行

python 复制代码
lock = threading.Lock()
with lock:  # 等价于 lock.acquire() + lock.release()
    # 线程安全的代码
    ...
4. 临时修改环境

python

运行

python 复制代码
with tempfile.TemporaryDirectory() as tmpdir:
    # 在临时目录中操作文件
    # 代码块结束后,tmpdir 自动删除

自定义上下文管理器

如果你需要管理自定义资源,可以通过以下两种方式创建上下文管理器:

方式 1:类实现

python

运行

python 复制代码
class MyResource:
    def __enter__(self):
        print("获取资源")
        return self  # 返回资源对象

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("释放资源")
        # 异常处理逻辑(如果需要)

with MyResource() as resource:
    # 使用 resource
    pass  # 输出:获取资源 → 释放资源
方式 2:装饰器 + 生成器(更简洁)

python

运行

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 语句的优势

  1. 自动资源管理 :避免手动调用 close()release() 等方法。
  2. 异常安全:即使代码块中抛出异常,资源也会被正确释放。
  3. 代码简洁 :减少样板代码(如 try-finally)。

常见内置上下文管理器

  • open():文件操作
  • threading.Lock():线程锁
  • tempfile.TemporaryFile():临时文件
  • contextlib.suppress():抑制特定异常
  • unittest.mock.patch():测试中的临时补丁

注意事项

  1. 变量作用域with 中定义的变量在代码块外仍可用,但资源可能已关闭。

    python

    运行

    python 复制代码
    with open('test.txt') as f:
        data = f.read()
    print(data)  # 正常访问,但 f.closed 为 True
  2. 嵌套 with 语句:支持多层资源管理。

    python

    运行

    python 复制代码
    with open('input.txt') as infile, open('output.txt', 'w') as outfile:
        outfile.write(infile.read())
  3. 异常处理__exit__() 方法可捕获并处理异常(通过 exc_type 参数判断)。

总结

with 语句通过上下文管理器实现了资源的自动获取和释放,是 Python 中优雅且安全的编程实践。常见于文件操作、数据库连接、网络会话等需要显式关闭资源的场景,能有效避免资源泄漏,提升代码可靠性。

4 python的三元表达式

Python 的三元表达式(Ternary Expression),也称为条件表达式(Conditional Expression),是一种简洁的语法结构,允许你在一行代码中根据条件选择不同的值。

它提供了一种比传统的if-else语句更紧凑的方式来表达条件逻辑。

基本语法

python

运行

python 复制代码
value_if_true if condition else value_if_false

执行逻辑

  • 如果conditionTrue,表达式返回value_if_true
  • 如果conditionFalse,表达式返回value_if_false

简单示例

示例 1:比较两个数的大小

python

运行

python 复制代码
a = 10
b = 20

max_value = a if a > b else b
print(max_value)  # 输出:20
示例 2:判断奇偶性

python

运行

python 复制代码
num = 7
result = "偶数" if num % 2 == 0 else "奇数"
print(result)  # 输出:奇数

与传统if-else的对比

传统写法

python

运行

python 复制代码
if num % 2 == 0:
    result = "偶数"
else:
    result = "奇数"

三元表达式

python

运行

python 复制代码
result = "偶数" if num % 2 == 0 else "奇数"

优势

  • 代码更简洁,减少行数。
  • 适合在赋值语句中直接使用,无需额外的代码块。

进阶用法

1. 嵌套三元表达式

可以在三元表达式中嵌套另一个三元表达式,但过度嵌套会降低代码可读性。

python

运行

python 复制代码
x = 15
result = "大正数" if x > 10 else ("小正数" if x > 0 else "非正数")
print(result)  # 输出:大正数
2. 与函数调用结合

python

运行

python 复制代码
def get_name():
    return "Alice"

def get_default():
    return "Guest"

name = get_name() if user_logged_in else get_default()
3. 在列表推导式中使用

python

运行

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]

注意事项

  1. 避免复杂条件 :如果条件或表达式过于复杂,建议使用传统的if-else语句,以保持代码可读性。

  2. 空值处理

    python

    运行

    python 复制代码
    # 如果 x 为 None,使用默认值 0
    value = x if x is not None else 0
  3. 执行顺序 :三元表达式是从左到右求值的,先判断condition,再根据结果选择返回值。

历史背景

Python 直到2.5 版本才引入三元表达式语法。在此之前,常见的替代方案是:

python

运行

python 复制代码
# Python 2.4及之前的写法
value = (value_if_false, value_if_true)[condition]

这种写法利用了布尔值可以作为列表索引(True为 1,False为 0)的特性,但可读性较差。

总结

三元表达式是 Python 中一种简洁的条件赋值语法,适用于简单的条件判断场景。它能让代码更紧凑,但应避免过度使用导致代码难以理解。当逻辑较为复杂时,建议优先使用传统的if-else语句。

python 复制代码
lines = content.count('\n') + 1 if content else 0
#怎么理解这个三元表达式

这行代码是用于统计文本内容中的行数,它巧妙地处理了空文件和非空文件两种情况。我来详细解释一下:

代码拆解

python

运行

复制代码
lines = content.count('\n') + 1 if content else 0

这行代码使用了 Python 的三元表达式(也称为条件表达式),等价于:

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

    python 复制代码
    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

运行

python 复制代码
content = "Line 1\nLine 2\nLine 3"
print(content.count('\n'))  # 输出 2
print(content.count('\n') + 1)  # 输出 3(正确的行数)
例 2:1 行文本(无换行符)

python

运行

python 复制代码
content = "Only one line"
print(content.count('\n'))  # 输出 0
print(content.count('\n') + 1)  # 输出 1(正确的行数)
例 3:空文件

python

运行

python 复制代码
content = ""
print(content.count('\n'))  # 输出 0
print(0 if not content else content.count('\n') + 1)  # 输出 0(正确的行数)

为什么需要这个逻辑?

在处理文件时,行数的统计不能简单地依赖换行符数量:

  • 最后一行无换行符 :大多数文本编辑器会在文件末尾自动添加换行符,但有些不会。因此,最后一行可能没有 \n,需要通过 + 1 补偿。
  • 空文件 :空文件不包含任何字符,包括换行符,因此行数应为 0

总结

这行代码通过以下步骤准确统计行数:

  1. 计算换行符数量。
  2. 对于非空文件,行数 = 换行符数量 + 1。
  3. 对于空文件,直接返回 0

这种方法既简洁又健壮,能够处理各种边界情况,是统计文本行数的经典实现。

5 猜数游戏

我写的真的是shit吧!!!!!我真的服了。。。

python 复制代码
import random

print("我们来玩猜数吧!")
ans = random.randint(1,1000)#生成随机数
num = int(input("请输入1-1000中的一个数"))
while True:
    if num > ans:
        print("猜大了")
        continue
    elif num < ans:
        print("猜小了")
        continue
    else:
        print("答对了")
        break

修改第一版:

python 复制代码
import random

print("我们来玩猜数吧!")
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  # 正确结束循环的语句

修改第二版,降低重复率:

python 复制代码
import random

print("我们来玩猜数吧!")
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

运行

python 复制代码
import random

print("猜数游戏(最多10次机会)")
ans = random.randint(1, 100)
max_attempts = 10
attempts = 0

while attempts < max_attempts:
    num = int(input(f"请输入1-100中的数(还剩{max_attempts - attempts}次):"))
    attempts += 1
    if num > ans:
        print("猜大了")
    elif num < ans:
        print("猜小了")
    else:
        print(f"恭喜!用了{attempts}次就猜对了!")
        break
else:  # 循环正常结束(未触发break)时执行
    print(f"次数用完啦!正确答案是{ans}")

2. 记录历史猜测记录

显示用户之前猜过的数字,帮助分析规律:

python

运行

python 复制代码
import random

print("带历史记录的猜数游戏")
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

运行

python 复制代码
import random

min_num, max_num = 1, 100
rounds = 1

print(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 += 1
        min_num, max_num = 1, max_num + 100  # 每轮范围+100
        print(f"恭喜过关!进入第{rounds}轮,范围扩大到1-{max_num}")
        ans = random.randint(min_num, max_num)

这些扩展虽然不复杂,但能让简单的逻辑变得更丰富,也能练习循环、条件判断、列表等基础语法的综合运用。如果想更深入,还可以加入难度选择(简单 / 中等 / 困难)、计分系统等,甚至用 GUI 库(如 tkinter)做个可视化界面~

相关推荐
AntBlack9 分钟前
拖了五个月 ,不当韭菜体验版算是正式发布了
前端·后端·python
大苏打seven16 分钟前
Docker学习笔记:Docker网络
笔记·学习·docker
.30-06Springfield26 分钟前
决策树(Decision tree)算法详解(ID3、C4.5、CART)
人工智能·python·算法·决策树·机器学习
我不是哆啦A梦26 分钟前
破解风电运维“百模大战”困局,机械版ChatGPT诞生?
运维·人工智能·python·算法·chatgpt
WJ.Polar37 分钟前
Python数据容器-list和tuple
开发语言·python
qq_2296441139 分钟前
LucidShape 2024.09 最新
python
Green1Leaves2 小时前
pytorch学习-9.多分类问题
人工智能·pytorch·学习
花好月圆春祺夏安2 小时前
基于odoo17的设计模式详解---装饰模式
数据库·python·设计模式
慕y2742 小时前
Java学习第十五部分——MyBatis
java·学习·mybatis
碣石潇湘无限路3 小时前
【AI篇】当Transformer模型开始学习《孙子兵法》
人工智能·学习