通过具有可变值的数据进行解析

2024-05-17 02:35:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我在当前的项目中遇到了一个令人困惑的问题。基本上,我是逐字节分析MIDI文件(是的,我必须这样做)。MIDI文件的结构使得一个音轨中任何给定事件的数据都是通过一系列称为“消息”的字节来传输的。MIDI设备知道基于状态码的消息类型,状态码是“消息”中的1-3字节,具有特定功能的特定id。你知道吗

我需要能够查看MIDI文件的数据,并将每个“消息”记录为一个自包含的对象,以便我可以将它们按顺序放置以供以后使用。我遇到的问题是,在处理数据时,我需要一种有效的方法来读取每个状态代码,并将其与我编写的处理该类型消息的数据的函数相匹配。我现在要做的是:

首先,在整个MIDI文件中的任何给定点,我查看接下来的3个字节,并将它们与我列出的所有可能的3字节MIDI状态码进行比较。这是我的第一个问题。对于所有3字节的状态码(相当于6个十六进制数字,这是MIDI编辑中经常使用的编码),第5-8位(又称第二个十六进制数字)指定当前消息影响的MIDI通道,该通道是可变且不可预测的。因为我无法预测频道,所以我需要将其视为外卡值。换言之,我需要以某种方式能够采取6位数字,并忽略第二个当我参照我的代码列表。我不认为我解释得很好,所以举个例子:

文件中的6位十六进制代码:Bn7800,其中n是通道号

6位代码列表:['Bn7800','Bn7900','FF2001','FF2F00',...]

我需要在列表中搜索正确的代码,而忽略第二个数字,因为我无法提前知道它是什么。你知道吗

我的另一个问题是,一旦我有了代码,我就需要调用我编写的处理特定状态代码的特定函数。我已经用它们对应的状态码命名了所有函数,但问题是,我不知道如何使用上面列表中找到的字符串来调用函数。例如:

我需要:Bn7800 在名单上,我找到了!所以我将它存储为一个名为stat_code = 'Bn7800'的新变量。 但是我不能这样调用我的函数->;self.stat_code(data) 因为stat_code不是我想要的函数名。我想要以stat_code值命名的函数。你知道吗

我不知道如何根据存储变量的值调用函数。你知道吗


抱歉,如果这是混淆,我发现很难解释完全没有试图解释整个MIDI文件结构。如果有不清楚的地方,请问我问题。谢谢!你知道吗


编辑:以下是一些代码:

self.event_status_codes = {'ff0002': ff_00_02,'ff01': ff_01,'ff02': ff_02,'ff03': ff03,'ff04': ff_04,'ff05': ff_05,'ff06': ff_06,'ff07': ff_07,'ff2001': ff_20_01,'ff2f00': ff_2f_00,'ff5103': ff_51_03,'ff5405': ff_54_05,'ff5804': ff_58_04,'ff5902': ff_59_02,'ff7f': ff_7f,'8n': _8n,'9n': _9n,'an': an,'bn': bn,'cn': cn,'dn': dn,'en': en,'bn7800': bn_78_00,'bn7900': bn_79_00,'bn7a': bn_7a,'bn7b00': bn_7b_00,'bn7c00': bn_7c_00,'bn7d00': bn7d00,'bn7e': bn_7e,'bn7f00': bn_7f_00,'f0': f0,'f7': f7}

    if track_data[hbc:hbc+3] in self.event_status_codes:  
        status_code = track_data[hbc:hbc+3]
        self.status_code(track_data)

作为参考,track_data是我正在解析的原始十六进制序列,hbc是一个简单的指针,它一次遍历一个十六进制数字。我发布了整个状态码字典,但现在我主要关注的是3位数字,因为它们通常指定频道号。而且,从技术上讲,它是一个Python字典,因为我必须将每个对应的函数命名为与实际代码稍有不同的名称,以使其可读性和功能性,因此可以忽略字典中每个键的值。你知道吗


Tags: 文件数据函数代码消息列表data字节
1条回答
网友
1楼 · 发布于 2024-05-17 02:35:55

I'm not sure how I can go about calling a function based on the value of a stored variable.

这可以通过按名称引用函数来实现。在您的问题中,您暗示您正在self上调用函数,这使它更容易:您可以使用getattr()函数获取包含函数指针的属性,然后调用它:

stat_code = 'B67800'
func = getattr(self, f'function_name_{stat_code}')
value = func()
# do stuff with value

如果您的函数是任何其他模块的一部分,也可以这样做—只需将该示例中的self替换为从中调用它的模块的名称即可。你知道吗

如果需要调用全局定义的函数(不是模块的一部分),则可能需要索引到locals()globals()

func = globals()[f'function_name_{stat_code}']
value = func()

相关问题 更多 >