用户指南,第4章:列表,流(I)和输出 ¶
在过去的两章中,我介绍了 biggerStream
对象的概念,它由 Note
和 Pitch
对象组成,并且我们甚至展示了一个音符在五线谱上的显示以及通过MIDI播放它。但是除非你与Cage和Webern竞争,争夺最没有音乐性的材料的地位,否则你可能希望分析、操作或创建多个音符。
Python有处理多个对象的方法, Duration
扩展了这些方法使其更具音乐性。让我们先看看Python是如何做的,然后再看看 music21
如何扩展这些方法。(如果你已经有一些编程经验,尤其是有Python经验的话,在创建下面描述的对象 music21
、 note1
和 note2
之后,可以直接跳到下面关于流的部分)。
假设你有两个音符,一个C和一个F#,在高音谱的中间位置。(如果使用三全音的概念让你不舒服,可以将第二个音符改为G;我们不介意;我们只会称呼你为格里高利教皇)。让我们创建这些音符:
使用列表处理多个对象 ¶
note3
让第一个音符变为二分音符,修改其时值(默认情况下,所有
from music21 import *
note1 = note.Note("C4")
note2 = note.Note("F#4")
对象都是四分音符):
Note
note1.duration.type = 'half'
note1.duration.quarterLength
2.0
note2.duration.quarterLength
要打印这些音符的音名(即没有八度或变音信息的音名),可以这样做:
step
print(note1.step)
C
print(note2.step)
但是假设你有三十个音符?那么输入"print(noteX.step)"三十次将会很痛苦。幸运的是,有一个解决办法: 我们可以将每个音符对象放入一个名为List的Python内置对象中,该对象可以存储多个其他对象(如音符或和弦,甚至可以是数字等)。要在Python中创建一个列表,请使用方括号([])将要放入列表中的内容括起来,用逗号分隔。让我们创建一个名为noteList的列表,其中包含note1和note2:
noteList
我们可以通过打印来检查noteList是否包含我们的音符:
noteList
print(noteList)
列表由方括号表示,括号内部有逗号分隔的内容,就像它们最初创建时一样。创建的动作在表示中得到了反映。这很好。中世纪的哲学家会赞同的。
现在我们可以编写一个两行的程序,将打印出noteList中每个音符的step。大多数现代语言都有一种方法可以对列表(也称为“数组”或有时称为“行”)中的每个成员(“元素”)执行某些操作。在Python中,这就是“for”命令。在输入这些行时,请确保在第二行的开头输入空格。(当你输入完"print(thisNote.step)"之后,可能需要按两次回车键才能看到结果。)
print(thisNote.step)
这里发生了什么?
C
F
这段代码的意思是Python应该按照noteList中的顺序逐个临时调用每个音符,并将该音符暂时称为“ for thisNote in noteList:
”(你可以随意使用任何名称,比如 thisNote
、 myNote
、 n
都可以,但是 currentNote
不行,因为 note
是一个模块的名称)。然后行末的“:”表示接下来的代码块将应用于noteList中的每一个音符。Python如何知道何时代码块的结束?很简单:所有属于循环的代码行都需要进行缩进(我通常使用四个空格或制表符。有些人使用两个空格。只要保持一致即可)。
并且如果我们再次编写我们的循环函数,我们将得到第三个音符:
3
for thisNote in noteList:
print(thisNote.step)
通过编写以下代码,我们可以找到noteList的第一个音符:
C
F
B
noteList[0]
注意,在列表中,第一个元素是
<music21.note.Note C>
,而不是 [0]
。有各种历史原因导致计算机从零开始计数列表,而不是从一开始,有些是好的,有些已经过时,但是我们需要适应这一点,如果我们想要完成任何工作。就像欧洲楼房和美国楼房的楼层编号方式一样。如果我们向前走一个音符,到达第二个音符,我们编写:
[1]
noteList[1]
我们还可以使用
<music21.note.Note F#>
,询问 noteList
在其中的位置,使用 note2
方法:
index()
noteList.index(n