8.代码风格&调试%结课竞赛

作业系统链接

1.代码风格

  • 前提:在对代码进行“修饰”之前,确保代码没有任何bug。
  • 非强制性:代码风格的学习不是强制性的,不影响后续课程的学习,但良好的代码风格有助于提高代码的可读性和维护性。

缩进与换行

代码布局 - 缩进
  1. 如果有开始定界符(如函数定义或控制结构),其余行的缩进需与开始定界符对齐。
  2. 需要额外的4个空格(相当于一个Tab键)来区分开传入参数和其他内容。
  3. 空格一般用于添加这种缩进,而Tab键通常用来保持行间的一致性。
  4. 对于多行if语句,需要一个额外的缩进来区分其他内容。
代码布局 - 换行
  1. 将所有行限制为最多79个字符。
  2. 一般语句接受隐式延续,但with语句等不支持,这时需要用反斜杠\来衔接。
  3. assert语句同样不支持隐式延续,也需要使用反斜杠\
  4. 多行if语句的缩进详见上一小节。
  5. 不鼓励使用复合语句(同一行上的多个语句)。

导入规范

导入本地模块/包
  • 当需要导入自己封装的模块时,使用import关键字直接导入。
  • 同目录下的模块可以直接通过名称导入。
导入Python库的模块/包
  • Python自带了丰富的基础库,可以通过简单的import语句来享用这些功能。
  • 使用from x import y语法,其中x是包前缀,y是没有前缀的模块名。

命名规则

  • 变量名只能包含字母、数字和下划线;变量名可以以字母或下划线开头,但不能以数字开头。
  • 变量名不应包含空格,可以使用下划线来分隔单词。
  • 不应使用Python关键字作为变量名。
  • 变量名应该简短且具有描述性。

关于空格

  • 圆括号、方括号或大括号内不需要多余空格。
  • 在逗号、分号或冒号之前及尾随逗号之后不需要多余空格。
  • 切片中两个冒号之间必须有相同的间距。
  • 函数调用的左括号前不需要多余空格。
  • 赋值运算符周围需要适当空格以提高可读性。

代码注释

  • 注释是对代码的解释说明,目的是帮助他人更容易理解代码。
  • 单行注释使用#符号,多行注释则使用三个引号'''"""
  • 在处理逻辑复杂的代码段中,有效注释量应至少占源代码的20%。

2. Debug

调试理论与常见错误
  • 程序作为状态机:将程序视为一个状态机,其执行过程即为状态的变化。出现bug意味着在某个环节发生了异常。
  • Bug分类
    • 理解需求差异产生的bug:设计偏离了最初规划的功能,导致无法满足用户需求。
    • 具体实现中的bug:技术原因导致程序不能很好地完成任务,通常是数学模型存在缺陷。
  • 常见错误
    1. 漏掉了末尾的冒号(如if语句、循环语句、函数定义)。
    2. 缩进错误,没有正确缩进。
    3. 英文符号写成中文符号(如引号、括号等)。
    4. 字符串和数字拼接错误。
    5. 变量未定义。
    6. “==”(比较运算符)与“=”(赋值运算符)混用。
    7. Tab键与空格混用。
利用IDE进行基本错误检测
  • 现代IDE(如VSCode)可以自动指出语法错误,这些错误通过本地Python解释器检测。
  • IDE仅能帮助识别基础问题,如函数书写方式或API调用方式;对于逻辑问题,通常需要从最终结果中判断并测试。
示例:质数查找
  • 示例代码展示了如何找出[10,20)之间的所有质数,同时指出了即使代码运行成功也可能存在隐藏的逻辑问题,这需要通过大量测试数据才能发现。
使用printassert进行调试
  • print方法简单易懂但可能使代码难以阅读和维护,在多线程或异步编程中可能导致输出混乱。
  • assert用于检查假设条件,但在生产环境中不应使用,且只能提供简单的错误提示。
利用logging模块进行日志记录
  • logging模块允许开发者设置不同级别的日志信息,包括DEBUG、INFO、WARNING、ERROR、CRITICAL。
  • 设置日志级别后,只有大于等于该级别的信息会被记录。
  • 示例:
    import logging
    logging.basicConfig(level=logging.DEBUG)
    logging.debug('This is a debug message')
    
在VSCode中配置调试
  • 创建launch.json文件以配置调试参数,例如添加"args"参数。
    {
        "version": "0.2.0",
        "configurations": [
            {
                "name": "Python: 当前文件",
                "type": "python",
                "request": "launch",
                "program": "${file}",
                "console": "integratedTerminal",
                "justMyCode": true,
                "args": ["6"]
            }
        ]
    }
    
  • 选择创建好的launch.json配置文件并打上断点运行。
使用pdb进行交互式调试
  • pdb是Python自带的调试器,可以通过命令行启动。
    • 命令:python -m pdb your_script.py
    • 常用命令:
      • breakb:设置断点
      • continuec:继续执行程序
      • listl:查看当前代码段
      • steps:进入函数
      • returnr:执行到当前函数返回
      • nextn:执行下一行
      • upu:返回到上个调用点
      • p x:打印变量x的值
      • exitq:退出调试器
      • help:获取帮助
其他调试技巧
  • 使用breakpoint():Python 3.7及以上版本引入了breakpoint()函数,它会在执行时暂停程序并启动调试器。
  • 推荐工具:除了pdb外,还有PySnooper等第三方库可以帮助更高效地调试。
3.结课竞赛
3.1题目描述

小鲸鱼最近学习了 Datawhale 的聪明办法学 Python 线下课程,这门课程的总成绩计算方法是:
总成绩 = 作业成绩 ×20%+×20%+ 小测成绩 ×30%+×30%+ 期末考试成绩 ×50%×50%
小鲸鱼想知道,这门课程自己最终能得到多少分。

输入格式

三个非负整数 A,B,CA,B,C,分别表示小鲸鱼的作业成绩、小测成绩和期末考试成绩。相邻两个数之间用一个空格隔开,三项成绩满分都是 100100 分。

输出格式

一个整数,即小鲸鱼这门课程的总成绩,满分也是 100100 分。

代码
def calculate_total_score(A, B, C):
  # 计算总成绩
  total_score = A * 0.20 + B * 0.30 + C * 0.50
  # 返回总成绩的整数部分
  return round(total_score)
# 读取输入数据
A, B, C = map(int, input().split())
# 计算并输出总成绩
print(calculate_total_score(A, B, C))

3.2.题目描述

亚运会开始了,小鲸鱼在拼命练习游泳准备参加游泳比赛,可怜的小鲸鱼并不知道鱼类是不能参加人类的奥运会的。
这一天,小鲸鱼给自己的游泳时间做了精确的计时(本题中的计时都按 2424 小时制计算),它发现自己从 aa 时 bb 分一直游泳到当天的 cc 时 dd 分,请你帮小鲸鱼计算一下,它这天一共游了多少时间呢?
小鲸鱼游的好辛苦呀,你可不要算错了哦。

输入格式

一行内输入四个整数,以空格隔开,分别表示题目中的 a,b,c,da,b,c,d。

输出格式

一行内输出两个整数 ee 和 ff,用空格间隔,依次表示小鲸鱼这天一共游了多少小时多少分钟。其中表示分钟的整数 ff 应该小于 6060。

代码

def calculate_swimming_time(a, b, c, d):
  # 将时间转换为分钟
  start_time = a * 60 + b
  end_time = c * 60 + d
  # 计算时间差
  time_difference = end_time - start_time
  # 将时间差转换为小时和分钟
  hours = time_difference // 60
  minutes = time_difference % 60
  return hours, minutes
# 读取输入数据
a, b, c, d = map(int, input().split())
# 计算并输出游泳时间
hours, minutes = calculate_swimming_time(a, b, c, d)
print(hours, minutes)

3.3.题目描述

小鲸鱼上初中了。鲸鱼妈妈认为小鲸鱼应该更加用功学习,所以小鲸鱼除了上学之外,还要参加鲸鱼妈妈为它报名的各科复习班。另外每周鲸鱼妈妈还会送它去学习朗诵、舞蹈和钢琴。但是小鲸鱼如果一天上课超过八个小时就会不高兴,而且上得越久就会越不高兴。假设小鲸鱼不会因为其它事不高兴,并且它的不高兴不会持续到第二天。请你帮忙检查一下小鲸鱼下周的日程安排,看看下周它会不会不高兴;如果会的话,哪天最不高兴。

输入格式

输入包括 77 行数据,分别表示周一到周日的日程安排。每行包括两个小于 1010 的非负整数,用空格隔开,分别表示小鲸鱼在学校上课的时间和鲸鱼妈妈安排它上课的时间。

输出格式

一个数字。如果不会不高兴则输出 00,如果会则输出最不高兴的是周几(用 1,2,3,4,5,6,71,2,3,4,5,6,7 分别表示周一,周二,周三,周四,周五,周六,周日)。如果有两天或两天以上不高兴的程度相当,则输出时间最靠前的一天。

代码

 def find_most_unhappy_day():
   max_hours = 0
   most_unhappy_day = 0
   for i in range(1, 8):
       school_hours, extra_hours = map(int, input().split())
       total_hours = school_hours + extra_hours
       if total_hours > max_hours:
           max_hours = total_hours
           most_unhappy_day = i
   if max_hours > 8:
       return most_unhappy_day
   else:
       return 0
# 执行函数并输出结果
print(find_most_unhappy_day())

3.4.题目描述

小鲸鱼的词汇量很小,所以每次做英语选择题的时候都很头疼。但是它找到了一种方法,经试验证明,用这种方法去选择选项的时候选对的几率非常大!
这种方法的具体描述如下:假设 maxnmaxn 是单词中出现次数最多的字母的出现次数,minnminn 是单词中出现次数最少的字母的出现次数,如果 maxn−minnmaxn−minn 是一个质数,那么小鲸鱼就认为这是个 Lucky Word,这样的单词很可能就是正确的答案。

输入格式

一个单词,其中只可能出现小写字母,并且长度小于 100100。

输出格式

共两行,第一行是一个字符串,假设输入的单词被验证是 Lucky Word,那么输出字符串 Lucky Word,否则输出 No Answer
第二行是一个整数,如果输入单词被验证是 Lucky Word,输出 maxn−minnmaxn−minn 的值,否则输出 00。

代码

 def is_prime(n):
   if n <= 1:
       return False
   for i in range(2, int(n**0.5) + 1):
       if n % i == 0:
           return False
   return True
def find_lucky_word(word):
   # 计算每个字母的出现次数
   letter_counts = {}
   for letter in word:
       if letter in letter_counts:
           letter_counts[letter] += 1
       else:
           letter_counts[letter] = 1
   # 找出出现次数最多的字母和出现次数最少的字母
   max_count = max(letter_counts.values())
   min_count = min(letter_counts.values())
   # 计算差值
   difference = max_count - min_count
   # 检查差值是否是质数
   if is_prime(difference):
       return "Lucky Word", difference
   else:
       return "No Answer", 0
# 读取输入数据
word = input().strip()
# 执行函数并输出结果
result, difference = find_lucky_word(word)
print(result)
print(difference)

3.5.题目描述

输入一个偶数 NN,验证 4∼N4∼N 所有偶数是否符合哥德巴赫猜想:任一大于 22 的偶数都可写成两个质数之和。如果一个数不止一种分法,则输出第一个加数相比其他分法最小的方案。例如 1010,10=3+7=5+510=3+7=5+5,则 10=5+510=5+5 是要被舍去的答案。

输入格式

第一行输入一个正偶数 NN

输出格式

输出 N−222N−2​ 行。对于第 ii 行:
首先先输出正偶数 2i+22i+2,然后输出等号,再输出加和为 2i+22i+2 且第一个加数最小的两个质数,以加号隔开。

代码

def is_prime(n):
   if n <= 1:
       return False
   for i in range(2, int(n**0.5) + 1):
       if n % i == 0:
           return False
   return True
def find_prime_pair(even_number):
   for i in range(2, even_number // 2 + 1):
       if is_prime(i) and is_prime(even_number - i):
           return i, even_number - i
   return None
# 读取输入数据
N = int(input())
# 验证从 4 到 N 的所有偶数
for i in range(2, N // 2 + 1):
   even_number = 2 * i
   prime_pair = find_prime_pair(even_number)
   if prime_pair:
       # 正确地打印出两个质数
       print(f"{even_number}={prime_pair[0]}+{prime_pair[1]}")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值