模块
第四模块

Module 4 - 任务列表

第一步:学习 Python 和正则表达式

  • 学习 Python 编程语言
💡

Windows 同学可以直接在 微软商店 中下载python哦~ 推荐下载3.11版本 目前3.12版本兼容性不是很好

💡

建议通过编写一些简单的 Python 脚本和正则表达式来实践,加深理解。

第二步:编写正则表达式

  • 正则表达式 1

    • 任务描述: 编写一个正则表达式,匹配字符串中的子串 "hello world"。

    指导:

    • 直接匹配固定的字符串,只需写出该字符串即可。

    答案:

    hello world
  • 正则表达式 2

    • 任务描述: 编写一个正则表达式,找到输入字符串中包含三个或更多连续元音字母(不区分大小写)的所有子串。

    指导:

    • 元音字母有 a、e、i、o、u
    • 使用字符类 [aeiouAEIOU] 匹配任意一个元音字母。
    • 使用量词 {3,} 表示匹配三个或更多。
    • 使用 \w* 去匹配连续元音前后的 0 到更多个字母

    答案:

    \w*[aeiouAEIOU]{3,}\w*
  • 正则表达式 3

    • 任务描述: 编写一个正则表达式,匹配完全符合航班代码格式的输入字符串,格式为 AA####,其中 AA 是两个大写字母的航空公司代码,#### 是三位或四位的航班号。

    指导:

    • ^ 和 $ 用于匹配字符串的开始和结束,确保整个字符串完全匹配指定格式。
    • [A-Z]2 匹配两个大写字母。
    • \d4 匹配三到四位数字。

    答案:

    ^[A-Z]{2}\d{3,4}$
💡

请将每个正则表达式分别保存到单独的文本文件中,文件名为 regex1.txtregex2.txtregex3.txt,文件中只包含对应的正则表达式内容。

第三步:编写棒球统计计数器脚本

  • 创建 Python 脚本文件

    • 新建一个名为 baseball.py 的 Python 脚本,用于计算圣路易斯红雀队球员在特定赛季的击球率。
  • 处理命令行参数

    • 脚本应接受一个命令行参数:输入文件的路径。
    • 如果未提供路径,程序应打印用法消息并退出。

    代码示例:

    import sys
     
    if len(sys.argv) != 2:
        print("Usage: python baseball.py <input_file>")
        sys.exit(1)
     
    input_file = sys.argv[1]
  • 读取并解析输入文件

    • 使用 open() 函数读取输入文件。
    • 使用正则表达式解析每一行,提取球员姓名、击球次数和安打数。

    指导:

    • 使用 re 模块的 match()search() 方法。
    • 正则表达式模式:
      ^([\w\s\.\'"]+?)\s+batted\s+(\d+)\s+times\s+with\s+(\d+)\s+hits\s+and\s+(\d+)\s+runs$
      • ([\w\s\.\'"]+?) 匹配球员姓名,包含字母、空格、点、单引号、双引号等字符。
      • \d+ 匹配一个或多个数字。

    代码示例:

    import re
     
    player_stats = {}
    player_stats_regex = re.compile(
        r'^([\w\s\.\'"]+?)\s+batted\s+(\d+)\s+times\s+with\s+(\d+)\s+hits\s+and\s+(\d+)\s+runs$'
    )
     
    with open(input_file, 'r') as file:
        for line in file:
            line = line.strip()
            match = player_stats_regex.match(line)
            if match:
                name = match.group(1).strip()
                at_bats = int(match.group(2))
                hits = int(match.group(3))
     
                if name not in player_stats:
                    player_stats[name] = {'at_bats': 0, 'hits': 0}
     
                player_stats[name]['at_bats'] += at_bats
                player_stats[name]['hits'] += hits
💡

在处理文件操作时,确保利用 tryexcept FileNotFoundError 来捕获文件可能不存在的异常情况。你可以通过以下方式更好地处理文件:

try:
    with open(input_file, 'r') as file:
        # 执行文件读取操作
except FileNotFoundError:
    print(f"错误: 文件 '{input_file}' 未找到。")
    sys.exit(1)

要点:

  • 使用 with open 语句可以确保文件在读取后自动关闭,无需手动调用 close() 方法。
  • 使用 try 和 except 来捕获 FileNotFoundError 异常,并在文件不存在时输出友好提示信息并安全退出程序。
  • 在文件操作完成后,无论是否遇到异常,都能够确保文件得到正确关闭。
  • 可以用同样的方式来捕获其他异常,如 PermissionError 等。

第四步:计算击球率并格式化输出

  • 计算每个球员的击球率

    • 击球率 = 总安打数 / 总击球次数
    • 保留三位小数,四舍五入。
  • 按照击球率排序并输出结果

    • 从高到低排序,如果击球率相同,顺序不做要求。
    • 输出格式为 球员姓名: #.###

    代码示例:

    # 计算击球率
    batting_averages = []
    for name, stats in player_stats.items():
        if stats['at_bats'] > 0:
            average = stats['hits'] / stats['at_bats']
            batting_averages.append((name, average))
     
    # 排序
    batting_averages.sort(key=lambda x: x[1], reverse=True)
     
    # 输出结果
    for name, average in batting_averages:
        print(f"{name}: {average:.3f}")
💡

使用 sorted() 函数或列表的 sort() 方法进行排序,注意排序的键。

第五步:测试你的脚本

  • 使用 样例输入文件 (opens in a new tab) 进行测试

    • 下载样例输入文件(如 cardinals-1940.txt),放在与你的脚本同一目录下。
  • 运行脚本并检查输出

    • 在命令行中运行:
      python baseball.py cardinals-1940.txt
    • 检查输出是否与示例输出一致。
💡

如果输出不一致,检查代码逻辑和正则表达式,确保数据正确解析和计算。

第六步:提交作业

  • 将代码和正则表达式文件提交到 GitHub 仓库

    • 提交以下文件:
      • regex1.txt
      • regex2.txt
      • regex3.txt
      • baseball.py
  • 遵守提交截止日期

    • 在截止日期之前将所有文件提交到 GitHub,未按时提交将导致本次作业记 0 分。
💡

确保提交的代码可运行,并包含必要的注释以提高可读性。

第七步:扩展学习(可选)

  • 深入学习正则表达式

    • 任务描述: 探索正则表达式的高级用法,理解更复杂的匹配模式。

    解答:

    • 非捕获组(Non-Capturing Groups):

      (?:pattern)

      解释:

      • 非捕获组用于分组但不捕获匹配的文本,这在提高匹配效率时很有用。
    • 回溯引用(Backreferences):

      (\w)\1

      解释:

      • (\w) 捕获一个单词字符,\1 引用第一个捕获组。
      • 该正则表达式匹配连续出现的相同字符,例如 "letter" 中的 "tt"。
    • 示例:

      import re
       
      # 匹配重复的单词
      text = "This is is a test test string"
      pattern = r'\b(\w+)\s+\1\b'
      matches = re.findall(pattern, text)
      print(matches)  # 输出:['is', 'test']

      解释:

      • 该正则表达式匹配连续重复的单词,如 "is is"、"test test"。
  • 优化代码性能

    • 任务描述: 学习如何优化 Python 代码,提高程序的运行效率。

    解答:

    • 使用列表推导式(List Comprehensions):

      # 常规方法
      squares = []
      for x in range(10):
          squares.append(x ** 2)
       
      # 列表推导式
      squares = [x ** 2 for x in range(10)]

      解释:

      • 列表推导式能够以更简洁的方式创建列表,提高代码可读性和执行效率。
    • 使用生成器表达式(Generator Expressions):

      # 列表推导式
      squares = [x ** 2 for x in range(1000000)]
       
      # 生成器表达式
      squares_gen = (x ** 2 for x in range(1000000))

      解释:

      • 生成器表达式在需要处理大量数据时,可以节省内存,因为它们不会一次性生成所有数据。
    • 示例:

      # 使用生成器计算大数据集的总和
      total = sum(x ** 2 for x in range(1000000))
      print(total)

      解释:

      • 生成器表达式在迭代时才生成数据,避免占用大量内存。
  • 数据可视化

    • 任务描述: 使用 Python 的数据可视化库,将球员的击球率绘制成图表。

    解答:

    • 安装 Matplotlib 库:

      pip install matplotlib
    • 示例代码:

      import matplotlib.pyplot as plt
       
      # 从之前的 batting_averages 列表中获取数据
      names = [item[0] for item in batting_averages]
      averages = [item[1] for item in batting_averages]
       
      # 绘制柱状图
      plt.figure(figsize=(10, 6))
      plt.bar(names, averages)
      plt.xlabel('球员姓名')
      plt.ylabel('击球率')
      plt.title('球员击球率排名')
      plt.xticks(rotation=90)
      plt.tight_layout()
      plt.show()

      案例

⚠️

案例图,数据不一样仅供参考

解释:

  • 使用 Matplotlib 库绘制柱状图,展示球员的击球率。

  • plt.xticks(rotation=90) 将球员姓名的标签旋转 90 度,避免重叠。

  • 注意事项:

    • 确保安装了 Matplotlib 库,使用 pip install matplotlib
    • 运行脚本时,图表会在新窗口中显示。
💡

通过这些扩展练习,你可以更深入地理解 Python 和数据分析,为后续的学习打下坚实的基础。

第八步:总结与反思

  • 总结所学内容

    • 在本模块中,你学习了:

      • Python 的基本语法和编程方法。
      • 正则表达式的使用和在 Python 中的应用。
      • 如何读取、解析和处理文本文件数据。
      • 数据的统计分析和排序方法。
      • 将数据结果可视化的基本技巧。
  • 反思与提高

    • 思考问题:

      • 在完成本次作业的过程中,你遇到了哪些挑战?
      • 你是如何解决这些问题的?
      • 通过本次练习,你对 Python 和正则表达式的理解有何提高?
    • 下一步计划:

      • 针对遇到的困难,制定学习计划,查阅相关资料加强理解。
      • 在后续的项目中,尝试应用所学的知识,巩固技能。
💡

反思是学习的重要环节,通过总结经验,你可以更有效地提升自己的编程能力。

评分标准

老师将根据以下内容对你的作业进行评分,总分为 50 分。

💡

作业(包括代码)必须在截止日期当天下课前提交到 GitHub(请尽早且频繁地提交)。未能在截止日期当天下课前提交的作业将得到 0 分。

正则表达式(15 分)

你的正则表达式文件应只包含正则表达式(无分隔符或标志),不应包含其他内容。

  • 正则表达式 1:正确并保存在名为 regex1.txt 的文件中(5 分)
  • 正则表达式 2:正确并保存在名为 regex2.txt 的文件中(5 分)
  • 正则表达式 3:正确并保存在名为 regex3.txt 的文件中(5 分)

棒球统计计数器(35 分)

  • 解决方案完全用 Python 编写,并保存在名为 baseball.py 的文件中(8 分)
⚠️

未使用 Python 3 编写的代码将至少丢失该类别的部分分数。

  • 正确使用一个或多个正则表达式来解析和提取输入文件每行的数据(8 分)
⚠️

不应使用 str.split 来提取数据。

  • 如果缺少命令行参数,脚本应 打印 (opens in a new tab) 使用消息(4 分)

  • 所有测试用例的输出均正确(15 分)

⚠️

这包括排序和四舍五入。