תרגול מחלקות: מוזיקה class־ית

תגיות:

בחסות נגה אוסין. תודה @Noga_o :slight_smile:

מוזיקה class־ית

בתרגיל זה ניצור סימפוניה קטנה, באמצעות מחלקות.

חלק 1

ממשו מחלקה של תו (Note). בפעולת האתחול של המופע, לכל תו יהיה:

  1. גובה צליל (Pitch) – אחד מהערכים דו־רה־מי־פה־סול־לה־סי.
  2. אורך (Length): כלומר, במשך כמה ביטים (יחידות זמן) התו ינוגן. (למוזיקאים: לשם הפשטות, נקרא לתו של רבע פשוט “ביט” בתרגיל זה. תו של חצי יהיה שני ביטים, וכן הלאה.)

משימות נוספות:

  1. צרו __str__ למחלקת התו שלכם. כל תו יהיה מהצורה Pitch(xLength). לדוגמה: Do(x1), Re(x2).
    על האות הראשונה בגובה הצליל להיות אות גדולה.
  2. על מנת להלחין את הסימפוניה שלנו הפעם, “נצנץ לך כוכב קטן”, עליכם ליצור תו של דו, באורך ביט אחד; תו של סול, באורך ביט אחד; תו של לה, באורך ביט אחד; תו של סול, באורך שני ביטים.

חלק 2

ממשו מחלקה של תיבה מוזיקלית (Bar). כל תיבה מסוגלת להכיל מספר קבוע של ביטים – לא פחות ולא יותר.
בדוגמה למעלה ישנן ארבע תיבות, עם ארבעה ביטים בכל אחת. התיבות מופרדות זו מזו באמצעות פסים אנכיים.
חדי העין ודאי ישימו לב שבתיבה השנייה והרביעית מצוירים רק שלושה תווים; זה מכיוון שתו “חלול” נחשב כשני ביטים, בעוד שאר התווים בדוגמה נחשבים כביט אחד בלבד.

  1. תחת פעולת האתחול, הגדירו לתיבה כמה ביטים היא יכולה להכיל. אם שמעתם על מונחים כמו “שלושה רבעים”, “ארבעה רבעים” או אפילו “שבע שמיניות” – זה בדיוק מה שאנחנו הולכים לממש כאן, אם כי בגרסה מעט פשוטה יותר. לתרגיל הנוכחי נממש שתי תיבות של ארבעה ביטים.
  2. ממשו את פעולת compose (הלחנה), בה התיבה תקבל מספר בלתי מוגבל של תווים, ותציב אותם בסדר בו היא קיבלה אותם. אם מספר הביטים של כלל התווים אינו תואם במדויק את הגדרת ההכלה של התיבה, החזירו False במקום להציב את התווים בתיבה. למשל, עבור תיבה המכילה ארבעה ביטים, התווים Do(x1), Re(x1), Mi(x1) לא יתקבלו מכיוון שמספר הביטים קטן מדי. התווים Do(x2), Re(x2), Mi(x1) לא יתקבלו אף הם, כיוון שמספר הביטים גדול מדי.
  3. ממשו את פעולת __str__ בצורה הבאה: אם התיבה הולחנה, יוחזרו התווים המאוחסנים בה משורשרים אחד לשני, כשביניהם פסיק ורווח. אם היא טרם הולחנה – החזירו את ההודעה “not composed yet”.

צרו את התיבה הראשונה והשנייה בשיר המופיע מטה!

  1. התיבה הראשונה אמורה להיראות כך: (Do(x1), Do(x1), Sol(x1), Sol(x1
  2. והשנייה, כך: (La(x1), La(x1), Sol(x2

חלק 3

הגיע הזמן לחבר את התיבות שלכן לסימפוניה! אין סימפוניה בלי תיבות, לכן פעולת האתחול של מחלקת הסימפוניה (Symphony) תקבל מספר בלתי מוגבל של תיבות. למחלקה זו תהיה פעולה אחת ויחידה – הדפסת כל התיבות, בזו אחר זו. תוכלו להוסיף קישוט אם בא לכם.

התוצאה הסופית אמורה להיראות כך:

Do(x1), Do(x1), Sol(x1), Sol(x1) || La(x1), La(x1), Sol(x2)

6 לייקים

כיצד אפשר לגרום למחשב להשמיע את הסימפוניה הנפלאה שכתבנו?

מושאר כתרגיל לקורא, כמובן

פיתרון
class Note:
    """A note class. Creates a note.

    Args:
        Pitch (str): The pitch of the note.
        Length (int): The length of the note.

    Attributes:
        Pitch (str): The pitch of the note.
        Length (int): The length of the note.
    """
    def __init__(self, Pitch, Length):
        self.Pitch = Pitch
        self.Length = Length

    def __str__(self):
        return f'{self.Pitch}(x{self.Length})'

class Bar:
    """A bar class. Unites notes together.

    Args:
        Length (int): The length of the bar.

    Attributes:
        Length (int): The length of the bar.
        notes (list): The notes that the bar consist from.
    """
    def __init__(self, Length):
        self.Length = Length
        self.notes = []

    def compose(self, *notes):
        """Compose the notes into the bar."""
        length_counter = self.Length
        bar_notes = []
        for note in notes:
            bar_notes.append(note)
            length_counter -= note.Length
        if length_counter != 0:
            return False
        self.notes = bar_notes
        return True

    def __str__(self):
        if self.notes:
            return ", ".join(str(note) for note in self.notes)
        return "Not composed yet"

class Symphony:
    """A symphony class. Unites bars together.

    Args:
        bars (Bar): Unknown number of Bars'.

    Attributes:
        Bars (list): The bars that had already composed.
    """
    def __init__(self, *bars):
        self.Bars = [bar for bar in bars if str(bar) != "Not composed yet"]

    def print_bars(self):
        """Print the symphony."""
        print(self)

    def __str__(self):
        return " || ".join(str(bar) for bar in self.Bars)
לייק 1

תרגיל ממש מהנה וממש עובר על מה שלמדנו בצורה מעולה ! ממליץ בחום.

פתרון
class Note:
    """ Represent a music note and

    Args:
        pitch (str): Pitch of a note
        Length (int): A length of a note represented by a number of bites

    Attributes:
        pitch (str): Pitch of a note
        Length (int): A length of a note.
    """

    def __init__(self, pitch, length):
        self.pitch = pitch
        self.length = length

    def __str__(self):
        return f"{self.pitch}(x{self.length})".title()


class Bar:
    """Represent a musical bar

    Args:
        size (int, optional): A max number of bits a bar can storage.
                              Gets a defualt size of 4.

    Attributes:
        size (int): A max number of bits a bar can storage.
        notes (list): A list of notes sets by the method compose.
                      Gets None as default value.
    """

    def __init__(self, size=4):
        self.size = size
        self.notes = None

    def __str__(self):
        if not self.notes:
            return "not composed yet"
        return ", ".join(map(str, self.notes))

    def compose(self, *melody, max_lenght=4):
        """Constracting a music bar by given notes and max size."""

        number_of_bites = sum([note.length for note in melody])
        if number_of_bites != max_lenght:
            return False
        self.notes = melody


class Symphony:
    """A Symmphony class constract by music's bars

    Args:
        bars (tuple): Music bars
        name (str): Symphony name

    Attributes:
        bars(tuple): Music bars
        name (str): Symphony name
    """

    def __init__(self, name, *bars):
        self.name = name
        self.bars = bars

    def __str__(self):
        return f"{self.name}:\n" + " || ".join(map(str, self.bars))

#output

Little Star:
Do(X1), Do(X1), Sol(X1), Sol(X1) || La(X1), La(X1), Sol(X2)
לייק 1
פתרון
class Symphony:
    def __init__(self, *bars):
        self.bars = bars
        
    def __str__(self):
        return ' || '.join(str(bar) for bar in self.bars)


class Bar:
    def __init__(self, length):
        self.legnth = length
        self.bar = None

    def __str__(self):
        if self.bar:
            return ', '.join(str(note) for note in self.bar)
        return "not composed yet"

    def compose(self, *notes):
        number_of_beats = sum(note.length for note in notes)
        if self.legnth != number_of_beats:
            return False
        self.bar = notes


class Note:
    def __init__(self, pitch, length):
        self.pitch = pitch
        self.length = length

    def __str__(self):
        return f"{self.pitch.capitalize()}(x{self.length})"


def play_twinkle_twinkle_little_star():
    bar1 = Bar(4)
    bar1.compose(Note("do", 1), Note("do", 1), Note("sol", 1), Note("sol", 1))
    bar2 = Bar(4)
    bar2.compose(Note("la", 1), Note("la", 1), Note("sol", 2))
    return Symphony(bar1, bar2)


print(play_twinkle_twinkle_little_star())
לייק 1

אחלה תרגיל! תודה רבה.

אני עכשיו בחיפושים אחר מודול שמקבל תו כמחרוזת ומחזיר הכל כSheet Music בשביל התרגול, אבל זה יצריך לשנות את הקוד דיי הרבה (ייצוג של האוקטבה של התו בנוסף לשם, בעיקר…)

פתרון
class Note:
    """A Note class, make a note representation with pitch and length.
    
    Args:
        pitch (str) = The note's pitch, represented as a string.
        length (int) = The note's length in beats. In 4/4 time, there are 4 beats.
    
    Notes:
        - At the moment, beats that are smaller than 1 are not supported.
        - For ease of use, you should use the solfège system (Do, Re, Mi...)
          to define the pitch.
    """
    
    def __init__(self, pitch, length):
        self.pitch = pitch
        self.length = length
    
    def __str__(self):
        return f"{self.pitch.title()}(x{self.length})"

class Bar:
    """A Bar class, construct bars of specific time from notes.
    
    Args:
        beat_count (int) = The bar's time, or number of beats per bar.
        notes (tuple) = A unlimited arg for passing notes to the bar.
    
    Attributes:
        composed (None or tuple) : A composed bar, after the insertion of notes.                           
    """
    
    def __init__(self, beat_count):
        self.beat_count = beat_count
    
    def compose(self, *notes):
        """Insert given notes to bar if note don't exceede the bar's beat_count.
        
        Args:
            notes (tuple) : The notes that construct the bar
        
        Returns:
            bool: Was the bar composed or not.
        """
        notes_beat_count = sum(note.length for note in notes)
        self.composed = None
        if notes_beat_count != self.beat_count:
            return False
        self.composed = notes
        return True
    
    def __str__(self):
        if self.composed:
            return ", ".join(str(note) for note in self.composed)
        else:
            return "Not composed yet."

class Symphony:
    """A Symphony class. Will convert bars to strings and string bars in order with seperation.
    
    Args:
        bars (tuple): An unlimited amount of bars to be returned as a symphony.
    """
    def __init__(self, *bars):
        self.bars = bars
    
    def __str__(self):
        return " || ".join(str(bar) for bar in self.bars)


def twinkle_twinkle():
    """Print a verse of the "Twinkle, Twinkle" song."""
    do1 = Note("Do", 1)
    sol1 = Note('Sol', 1)
    sol2 = Note('Sol', 2)
    la1 = Note('La', 1)
    bar1 = Bar(4)
    bar2 = Bar(4)
    bar1.compose(do1, do1, sol1, sol1)
    bar2.compose(la1, la1, sol2)
    symphony = Symphony(bar1, bar2)
    print(symphony)

twinkle_twinkle()

The output:

Do(x1), Do(x1), Sol(x1), Sol(x1) || La(x1), La(x1), Sol(x2)
לייק 1

תרגיל נחמד מאוד. לקחתי על עצמי להכניס גם את המשך השיר לסימפוניה שלי

Bitter Sweet Symphony of Destruction
class Note:
    """A class for note represtation including pitch and length

    Args:
        pitch (str): The note's pitch (Do, Re, Mi...)
        length (int): The number of beats the note lasts for.

    Attributes:
        pitch (str): The note's pitch (Do, Re, Mi...)
        length (int): The number of beats the note lasts for.
    """
    def __init__(self, pitch, length):
        self.pitch = pitch
        self.length = length

    def __str__(self):
        return f'{self.pitch.title()}(x{self.length})'


class Bar:
    """A bar class, represents an ordered collection of notes

    Args:
        beats (int): The number of beats in the bar.

    Attributes:
        beats (int): The number of beats in the bar.
        notes (list): A list of the bars notes in order.
                        Is created empty.
    """
    def __init__(self, beats):
        self.beats = beats
        self.notes = []

    def compose(self, *notes):
        """Adds notes to the bar in their given order.

        Args:
            *notes (Note): Any number of Note instances.

        Returns:
            bool: False.
                    Only if the given notes do not correspond to the bar's length.
        """
        total_beats = 0
        for note in notes:
            total_beats += note.length
        if total_beats != self.beats:
            return False
        self.notes = [*notes]

    def __str__(self):
        if not self.notes:
            return 'Not yet composed'
        bar = ''
        for note in self.notes:
            bar += f'{str(note)}, '
        return bar.rstrip(', ')


class Symphony:
    """A symphony class made up of several bars that form a melody.

    Args:
        *bars (Bar): Any number of Bar instances.

    Attributes:
        bars (list): A list of the symphony's bars.
    """
    def __init__(self, *bars):
        self.bars = [*bars]

    def __str__(self):
        symphony = ''
        for bar in self.bars:
            symphony += str(bar) + r'||'
        return symphony.rstrip(r'||')


do_1 = Note('do', 1)
sol_1 = Note('sol', 1)
la_1 = Note('la', 1)
sol_2 = Note('sol', 2)
fa_1 = Note('fa', 1)
mi_1 = Note('mi', 1)
re_1 = Note('re', 1)
do_2 = Note('do', 2)
re_2 = Note('re', 2)


first_bar = Bar(4)
second_bar = Bar(4)
third_bar = Bar(4)
fourth_bar = Bar(4)
fifth_bar = Bar(4)
sixth_bar = Bar(4)
first_bar.compose(do_1, do_1, sol_1, sol_1)
second_bar.compose(la_1, la_1, sol_2)
third_bar.compose(fa_1, fa_1, mi_1, mi_1)
fourth_bar.compose(re_1, re_1, do_2)
fifth_bar.compose(sol_1, sol_1, fa_1, fa_1)
sixth_bar.compose(mi_1, mi_1, re_2)
BARS = [first_bar, second_bar, third_bar, fourth_bar, fifth_bar, sixth_bar]

twinkle = Symphony(
    BARS[0],
    BARS[1],
    BARS[2],
    BARS[3],
    BARS[4],
    BARS[5],
    BARS[4],
    BARS[5],
    BARS[0],
    BARS[1],
    BARS[2],
    BARS[3])
print(twinkle)

Output

Do(x1), Do(x1), Sol(x1), Sol(x1)||La(x1), La(x1), Sol(x2)||Fa(x1), Fa(x1), Mi(x1), Mi(x1)||Re(x1), Re(x1), Do(x2)||Sol(x1), Sol(x1), Fa(x1), Fa(x1)||Mi(x1), Mi(x1), Re(x2)||Sol(x1), Sol(x1), Fa(x1), Fa(x1)||Mi(x1), Mi(x1), Re(x2)||Do(x1), Do(x1), Sol(x1), Sol(x1)||La(x1), La(x1), Sol(x2)||Fa(x1), Fa(x1), Mi(x1), Mi(x1)||Re(x1), Re(x1), Do(x2)
2 לייקים
פתרון
class Note:
    def __init__(self, pitch, length):
        self.pitch = pitch.title()
        self.length = length

    def __str__(self):
        return f"{self.pitch}(x{self.length})"


class Bar:
    def __init__(self, length):
        self.length = length
        self.notes = None

    def __str__(self):
        if self.notes is None:
            return "not composed yet"
        return ", ".join(str(note) for note in self.notes)

    def compose(self, *notes):
        if sum(map(lambda note: note.length, notes)) != self.length:
            return False
        self.notes = list(notes)


class Symphony:
    def __init__(self, *bars):
        self.bars = bars

    def __str__(self):
        return " || ".join(str(bar) for bar in self.bars)
לייק 1