9021_TUT_3 第 25 次课练习题
练习 1
题目描述
给定两个整数 m 和 n,其中:
m表示重复单元(pattern)的数量。n表示每个单元中元素(下划线)的数量。
目标是生成一个字符串,规则如下:
- 每个单元包含
n个下划线(_),以|分隔。 - 各单元之间以
*连接。
我的解法
def generate_struct(n):
return '|'.join(n * ['_'])
def f1(m, n):
return ' * '.join(m * [generate_struct(n)])思路
我将每个单元视为独立的结构。先构建最小单元(用 | 连接下划线),再用 join() 以 * 拼接各单元。
辅助函数 generate_struct(n)
生成基础结构:将 n 个下划线以 | 连接。
例如 n = 2 时,结果为 "_|_"。
标准解法
def f1(m, n):
return ' * '.join('|'.join('_' for _ in range(n)) for _ in range(m))简洁表达
内层 join 用生成器表达式创建 n 个下划线以 | 连接的字符串;外层 join 重复 m 次,用 * 连接各单元。
两种方案的对比:我的解法注重模块化(拆分为小函数),标准解法将一切压缩为一行列表推导式。
练习 2
题目描述
根据给定数字 n 的各位数字生成图案:
- 奇数位显示黑色方块(⬛)。
- 偶数位显示白色方块(⬜)。
我的解法
def f2(n):
ans = ''
for i in str(n):
if int(i) % 2 == 0:
ans += '⬜'
else:
ans += '⬛'
print(ans)思路
- 将数字
n转为字符串,逐位遍历。 - 用取模运算(
% 2)判断奇偶。 - 奇数位追加黑色方块,偶数位追加白色方块。
- 打印最终字符串。
标准解法
def f2(n):
print(''.join({0: '\u2b1c', 1: '\u2b1b'}[int(d) % 2] for d in str(n)))Martin 博士的解法更 Pythonic:用字典和生成器表达式简化代码,Unicode 转义序列直接引用方块符号。
练习 3
题目描述
将数字 n 视为不同进制(2 到 10)下的表示,将其转换为十进制值(仅对合法进制有效)。
例如 n = 2143:
2143在 5 进制下等于十进制的298。2143在 6 进制下等于十进制的495。- 以此类推。
我的解法
def f3(n: int):
for i in range(2, 11):
try:
value = int(str(n), i)
print(f'{n} is {value} in base {i}')
except ValueError:
pass思路
- 遍历进制 2 到 10。
- 用
int(str(n), i)将n作为i进制数转换为十进制。若数字不合法则抛出ValueError,跳过该进制。 - 用
try-except处理非法进制。
标准解法
def f3(n):
n_as_string = str(n)
min_base = max(2, max({int(d) for d in n_as_string}) + 1)
for b in range(min_base, 11):
print(f'{n} is {int(n_as_string, b)} in base {b}')标准解法通过集合推导提取最大数字来确定最小合法进制,跳过非法进制而无需异常处理。
练习 4
题目描述
创建函数 f4(n, base),返回字典 D:
- 键为
0到n的整数。 - 值为以
base进制表示的元组(从十进制转换而来)。
我的解法
def convert_to_base(n, base):
if n == 0:
return '0'
digits = []
while n:
digits.append(str(n % base))
n //= base
return ''.join(digits[::-1])
def f4(n: int, base: int):
D = {}
for i in range(0, n + 1):
D[i] = tuple(map(int, convert_to_base(i, base)))
return D思路
- 辅助函数
convert_to_base(n, base)用辗转相除法将十进制数转换为指定进制字符串。 - 主函数遍历
0到n,转换每个数并存为元组。
关于 map() 的 Pythonic 性
map() 来自函数式编程范式,现在通常用列表推导式代替,因为后者更简洁、易读:
D[i] = tuple([int(digit) for digit in convert_to_base(i, base)])标准解法
def f4(n, base):
D = {0: (0,)}
for m in range(1, n + 1):
digits = []
p = m
while p:
digits.append(p % base)
p //= base
D[m] = tuple(reversed(digits))
return D两种解法均正确。我的解法用辅助函数增加了模块化,标准解法更简洁,直接在主函数中完成转换。
练习 5
先运行这段代码:
print(0.1 + 0.2)结果不是 0.3,而是 0.30000000000000004,这是为什么?
题目描述
此练习旨在揭示计算机浮点运算的局限性。计算机以二进制格式存储浮点数,通常会引入精度误差。
解法
def f5(integral_part, fractional_part):
precision = len(str(fractional_part))
a_float = float(str(integral_part) + '.' + str(fractional_part))
simple_precision = f'{a_float:.{precision}f}'
extended_simple_precision = simple_precision + '0' * precision
double_precision = f'{a_float:.{precision * 2}f}'
print('With', precision * 2, 'digits after the decimal point, ', end='')
if extended_simple_precision == double_precision:
print(simple_precision, 'prints out with', precision, 'trailing',
precision == 1 and 'zero,' or 'zeroes,', 'namely, as',
extended_simple_precision
)
else:
print(simple_precision, 'prints out as', double_precision)通过简单精度(simple_precision)和双精度(double_precision)对比,展示浮点数并非总是以我们期望的方式存储。
练习 6
题目描述
给定:
- 列表
L,包含多个等长度n的整数子列表。 - 列表
fields,是{1, ..., n}的一个排列。
要求用多键排序机制对 L 排序:先按 fields[0] 指定位置排序,相等时按 fields[1],以此类推。
例如 fields = [2, 1] 表示先按第二个元素排序,相同时按第一个元素排序。
我的解法
def f6(L, fields):
return sorted(L, key=lambda x: [x[i-1] for i in fields])sorted() 函数根据 key 排序。lambda 函数按 fields 中指定的位置提取每个子列表的元素,x[i-1] 是因为 fields 从 1 开始索引,而 Python 列表从 0 开始。
标准解法
def f6(L, fields):
return sorted(L, key=lambda x: tuple(x[i - 1] for i in fields))为什么用元组? 元组不可变,Python 内置排序可以高效比较元组。两种解法均正确,标准解法用元组更符合 Python 惯例。
贡献者
最近更新
Involution Hell© 2026 byCommunityunderCC BY-NC-SA 4.0