You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修正Python中带参数的transpose装饰器以实现合法音符移调?

问题背景

音乐中的七个音符对应如下符号:

Note    Symbol
Do       c
Re       d
Mi       e
Fa       f
Sol      g
La       a
Si       b

八度范围为1到7,示例格式如下:

"c1": 第1八度的Do,
"d1": 第1八度的Re,
"g1": 第1八度的Sol,
"c2": 第2八度的Do,
"a5": 第5八度的La.

现有预定义函数get_note(),返回音符+八度数字格式的字符串(比如d4)。需要实现一个带整数参数的装饰器transpose(n),用来调整音符的八度:

  • 0:完全不修改
  • 1:升高1个八度
  • -3:降低3个八度

限制规则:调整后的八度不能低于1,也不能高于7。

调用示例:

from random import choice

@transpose(2)  # 传入八度调整参数
def get_note():
    note = choice(['c', 'd', 'e', 'f', 'g', 'a', 'b'])
    octave = choice(range(1, 8))
    print(f"Initial: {note}{octave}")
    return f"{note}{octave}"

returned = get_note()
print(f"result: {returned}")

示例1:
输入:d4,调整参数-3
输出:d1

示例2:
输入:c7,调整参数2
输出:c7


现有装饰器的问题

以下是我编写的transpose装饰器,存在多处错误:

def transpose(*args):
    def wrapper(func):
        print(*args)
        note, octode = func()
        octode = int(octode)
        print(octode)
        octode += int(*args)
        print(octode)
        return f"{note}{octode}"

    return wrapper

@transpose
def get_note():
    ...  # 函数逻辑,返回f"{note}{octode}"

需要修正的问题点
  1. 装饰器结构错误:带参数的装饰器需要三层嵌套结构,原代码仅两层,无法正确接收@transpose(2)这类带参数的调用。外层函数应先接收调整参数,再返回装饰器函数,最后才是包裹原函数的执行逻辑层。
  2. 返回值拆分错误:get_note()返回的是完整字符串(如d4),原代码直接用note, octode = func()拆分,会触发字符串拆包错误,需要手动分离音符字母和八度数字部分。
  3. 变量名拼写错误:多处将octave(八度)拼写成octode,属于低级语法错误。
  4. 缺少范围限制:调整后的八度没有被约束在1-7之间,违反需求规则。
  5. 冗余调试代码:保留了不必要的print语句,不符合生产代码规范。

修正后的装饰器实现
def transpose(shift):
    def decorator(func):
        def wrapper():
            # 获取原函数返回的音符字符串
            note_str = func()
            # 拆分音符字母与八度数字
            note = ''
            octave_str = ''
            for char in note_str:
                if char.isalpha():
                    note += char
                else:
                    octave_str += char
            octave = int(octave_str)
            # 计算新八度并限制在1-7范围内
            new_octave = max(1, min(octave + shift, 7))
            # 返回调整后的音符
            return f"{note}{new_octave}"
        return wrapper
    return decorator

# 测试用例
from random import choice

@transpose(2)
def get_note():
    note = choice(['c', 'd', 'e', 'f', 'g', 'a', 'b'])
    octave = choice(range(1, 8))
    print(f"Initial: {note}{octave}")
    return f"{note}{octave}"

returned = get_note()
print(f"result: {returned}")

修正说明

  • 改为三层嵌套结构,完美支持带参数的装饰器调用;
  • 通过遍历字符串拆分音符与八度,避免直接拆包报错;
  • 使用max(1, min(...))强制约束八度范围,符合需求规则;
  • 修正变量名拼写错误,移除冗余调试代码。

内容的提问来源于stack exchange,提问作者Albina Hakobyan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 11:00:47