试图了解这个python类正在做什么/它是如何工作的

时间:2016-03-19 00:15:05

标签: python

我是编程和查看其他人编写的代码的新手。我找到了一个在python中生成音乐的简洁程序,我真的很想了解它在做什么(链接/信用在这里:http://davywybiral.blogspot.com.br/2010/09/procedural-music-with-pyaudio-and-numpy.html)。

具体来说,我已经挂断了属于程序开头的类的变量intervals。这是班级:

class Scale:

  def __init__(self, root, intervals):
    self.root = Note(root.index, 0)
    self.intervals = intervals

  def get(self, index):
    intervals = self.intervals
    if index < 0:
      index = abs(index)
      intervals = reversed(self.intervals)
    intervals = itertools.cycle(self.intervals)
    note = self.root
    for i in xrange(index):
      note = note.transpose(intervals.next())
    return note

  def index(self, note):
    intervals = itertools.cycle(self.intervals)
    index = 0
    x = self.root
    while x.octave != note.octave or x.note != note.note:
      x = x.transpose(intervals.next())
      index += 1
    return index

  def transpose(self, note, interval):
    return self.get(self.index(note) + interval)

在节目结束时,有程序播放某些和弦的说明,以下是:

scale = Scale(root, [2, 1, 2, 2, 1, 3, 1])

这是我不清楚的第二个论点;我知道程序正在循环使用这些值,但我不知道它们在控制什么。我只是知道改变它们会在最糟糕的情况下混乱。

我可以就这些线路发生的事情获得一些指导吗?

2 个答案:

答案 0 :(得分:0)

值是笔记之间的间隔。所以在这种情况下: 2 1 2 2 1 3 1,根据您提供的链接上的说明,是谐波次要(也见wiki)。

因此,如果更改数字,则更改音符之间的距离/间隔以及音阶。

假设root是A,提供以下比例:

A B C D E F G# A    Actual notes
 2 1 2 2 1 3  1     The intervals between the notes

如果列表为[2 1 2 2 1 2 1],则比例将是次要的:

A B C D E F G A  Actual notes
 2 1 2 2 1 2 1   The intervals between the notes

因此,如果你想给它一个C大调,你应该放弃:

C D E F G A B C in a list of intervals:
 2 2 1 2 2 2 1

我希望这会有所帮助。

干杯!

答案 1 :(得分:0)

此代码的核心是迭代器的概念。迭代器是&#34;指针&#34;进入列表,例如间隔,用于在列表中移动。 例如

for i in [1, 2, 3]:
    print i

该代码遍历列表[1,2,3]并打印.. 1 2 3

虽然迭代器可以让你计算&#34;通过列表,如果需要迭代器,列表将自动转换为迭代器。

所以这段代码在get()的代码中交替使用了区间列表和各种迭代器,这让人很困惑。它基本上做了一堆有序的改组音符。

这大致就是它的作用(我对音乐的了解和你对编程的了解:)。看起来它听起来像巴赫。

class Scale:   # class declaration.

  def __init__(self, root, intervals):
    """
    __init__ is the constructor.  It gets called automatically
    whenever a new instance is created.  That is, it's called 
    automatically when a new Scale is made, e.g. on this line:

      scale = Scale(root, [2, 1, 2, 2, 1, 3, 1]) 

    """
    self.root = Note(root.index, 0)  # the root is a note?
    self.intervals = intervals # this just saves the list [2, 1,..

  def get(self, index):
    """
    called whenever someone goes.. scale.get(index) or within
    this class it's called as self.get(index).

    """
    # get a reference to the intervals (no copy is made)
    # at this point we could iterate over it from the start of the
    # intervals to the end of the intervals e.g. 2, 1, 2, 2, ..
    intervals = self.intervals  

    # if the index is less than zero 
    if index < 0:  
      # get the absolute value, e.g. -5 goes to 5
      index = abs(index)

      # makes intervals an iterator that counts backwards
      # e.g. [1, 3, 1, 2...] 
      # this "mirrors" the intervals if you like
      intervals = reversed(self.intervals)

    # makes intervals "loop forever" you can keep iterating and 
    # when you get to the end, loop around to the start again.
    intervals = itertools.cycle(self.intervals)

    # swap this note with the next index notes
    note = self.root
    for i in xrange(index):
      note = note.transpose(intervals.next())
    return note

  def index(self, note):
    """
    Finds the index of the next note and transposes 
    a bunch of them to.

    """
    intervals = itertools.cycle(self.intervals)
    index = 0
    x = self.root
    # keep trying notes until we have a different note in 
    # this octave
    while x.octave != note.octave or x.note != note.note:
      x = x.transpose(intervals.next())
      index += 1
    return index

  def transpose(self, note, interval):
    """
    Gets the note one interval away.
    Which also transposes a bunch of things.

    """
    return self.get(self.index(note) + interval)