Домашни > Pitches love the D > Решения > Решението на Екатерина Стоянова

Резултати
9 точки от тестове
0 точки от учител

9 точки общо

32 успешни теста
5 неуспешни теста
Код
Скрий всички коментари

  1class Tone:
  2    VALID_NOTES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] # list to use the indexes
  3
  4    def __init__(self, tone):
  5        self.tone = tone
  6
  7    def __str__(self):
  8        return str(self.tone)
  9
 10    def __eq__(self, other):
 11        return self.VALID_NOTES.index(self.tone) == self.VALID_NOTES.index(other.tone)
 12
 13    def __hash__(self):
 14        return hash(self.tone)
 15
 16    def __and__(self, other): # using it for the major and minor functions for convenience
 17        return abs(self.VALID_NOTES.index(self.tone) - self.VALID_NOTES.index(other.tone))
 18
 19    def __add__(self, other):
 20        if isinstance(other, Tone):
 21            return Chord (self, other)
 22        elif isinstance(other, Interval):
 23            new_tone_index = (self.VALID_NOTES.index(self.tone) + other.number_of_semitones) % 12
 24            new_tone = self.VALID_NOTES[new_tone_index]
 25            return Tone(new_tone)
 26        else:
 27            raise TypeError("Invalid operation")
 28
 29    def __sub__(self, other):
 30        if isinstance(other, Tone):
 31            return Interval(self&other)
 32        elif isinstance(other, Interval):
 33            new_tone_index = (self.VALID_NOTES.index(self.tone) - other.number_of_semitones) % 12
 34            new_tone = self.VALID_NOTES[new_tone_index]
 35            return Tone(new_tone)
 36        else:
 37            raise TypeError("Invalid operation")
 38
 39
 40class Interval:
 41    SEMITONES = {
 42        0: "unison",
 43        1: "minor 2nd",
 44        2: "major 2nd",
 45        3: "minor 3rd",
 46        4: "major 3rd",
 47        5: "perfect 4th",
 48        6: "diminished 5th",
 49        7: "perfect 5th",
 50        8: "minor 6th",
 51        9: "major 6th",
 52        10: "minor 7th",
 53        11: "major 7th"
 54    }
 55
 56    def __init__(self, number_of_semitones):
 57        self.number_of_semitones = number_of_semitones % 12
 58
 59    def __str__(self):
 60        return self.SEMITONES[self.number_of_semitones]
 61
 62    def __add__(self, other):
 63        if isinstance(other, Tone):
 64            raise TypeError ("Invalid operation")
 65        elif isinstance(other, Interval):
 66            return Interval(self.number_of_semitones + other.number_of_semitones)
 67
 68    def __neg__(self):
 69        return Interval(-self.number_of_semitones)
 70
 71
 72class Chord:
 73    CHROMATIC_SCALE = Tone.VALID_NOTES
 74
 75    def __init__(self, main_tone, *tones):
 76        self.main_tone = main_tone
 77        #remove duplicates by first using a set and then back to a list
 78        unique_tones = list(set(tones) | {main_tone})
 79        if len(unique_tones) < 2:
 80            raise TypeError("Cannot have a chord made of only 1 unique tone")
 81        self.tones = unique_tones
 82
 83    def __str__(self):
 84        to_return = str(self.main_tone)
 85        main_tone_idx = self.CHROMATIC_SCALE.index(to_return)
 86        tone_str = {str(tone) for tone in self.tones}
 87        # sorting based on the main tone, NOT based on the indexation in Valid_Tones
 88        for tone in Tone.VALID_NOTES[main_tone_idx + 1:]:
 89            if tone in tone_str:
 90                to_return += "-" + tone
 91        for tone in Tone.VALID_NOTES[:main_tone_idx]:
 92            if tone in tone_str:
 93                to_return += "-" + tone
 94        return to_return
 95
 96    def is_minor(self):
 97        for t in self.tones:
 98            if self.main_tone != t and (self.main_tone & t) == 3:  # 3 is equal to the index of minor 3rd
 99                return True
100        return False
101
102    def is_major(self):
103        for t in self.tones:
104            if self.main_tone != t and (self.main_tone & t) == 4:  # 4 is equal to the index of major 3rd
105                return True
106        return False
107
108    def is_power_chord(self):
109        is_it_minor = self.is_minor()
110        is_it_major = self.is_major()
111        return not (is_it_major or is_it_minor)
112
113    def __add__(self, other):
114        if isinstance(other, Tone):
115            return Chord(self.main_tone, *(self.tones + [other]))
116        elif isinstance(other, Chord):
117            return Chord(self.main_tone, *(self.tones+other.tones))
118
119    def __sub__(self, other):
120        if isinstance(other, Tone) and other in self.tones:
121            if len(self.tones) >= 3:
122                other_index = self.tones.index(other)
123                return Chord(self.main_tone, *(self.tones[other_index + 1:] + self.tones[:other_index]))
124            else:
125                raise TypeError("Cannot have a chord made of only 1 unique tone")
126        else:
127            raise TypeError(f"Cannot remove tone {other} from chord {self}")
128
129    def transposed(self, interval):
130        to_transpose = list()
131        to_transpose.append(self.main_tone+interval)
132        for t in self.tones:
133            to_transpose.append(t + interval)
134        return Chord(*to_transpose)

....FFF....................F.......F.
======================================================================
FAIL: test_is_major (test.TestBasicChordFunctionality.test_is_major)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 107, in test_is_major
self.assertTrue(a_major_chord.is_major())
AssertionError: False is not true

======================================================================
FAIL: test_is_minor (test.TestBasicChordFunctionality.test_is_minor)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 90, in test_is_minor
self.assertTrue(a_minor_chord.is_minor())
AssertionError: False is not true

======================================================================
FAIL: test_is_power_chord (test.TestBasicChordFunctionality.test_is_power_chord)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 116, in test_is_power_chord
self.assertFalse(a_minor_chord.is_power_chord())
AssertionError: True is not false

======================================================================
FAIL: test_subtract_interval_from_tone_left_side_error (test.TestOperations.test_subtract_interval_from_tone_left_side_error)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 235, in test_subtract_interval_from_tone_left_side_error
self.assertEqual(str(err.exception), INVALID_OPERATION)
AssertionError: "unsupported operand type(s) for -: 'Interval' and 'Tone'" != 'Invalid operation'
- unsupported operand type(s) for -: 'Interval' and 'Tone'
+ Invalid operation

======================================================================
FAIL: test_tone_subtraction_inverse (test.TestOperations.test_tone_subtraction_inverse)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 178, in test_tone_subtraction_inverse
self.assertEqual(str(perfect_4th), "perfect 4th")
AssertionError: 'perfect 5th' != 'perfect 4th'
- perfect 5th
? ^
+ perfect 4th
? ^

----------------------------------------------------------------------
Ran 37 tests in 0.002s

FAILED (failures=5)

Дискусия
Виктор Бечев
01.11.2024 19:03

Както споменаваме често - ползвайте каквото ви е кеф в стандартната библиотека. `__hash__` е стандартен дъндър от обектният протокол, така че ползвай на воля. :)
Екатерина Стоянова
31.10.2024 17:30

Благодаря Ви! Аз иначе открих проблема - Tone не е "hashable" по подразбиране и затова не е тръгвало. Проблем ли е, че ще ползвам функцията _ _hash_ _(), понеже я видях в GeeksForGeeks, но поне в презентациите не я намерих?
Виктор Бечев
31.10.2024 16:45

Ако правилно съм те разбрал, то проблемът ти се свежда до ниво на абстракция, което не е проблем да обсъдим. Как да сортирам тоновете, без да дефинирам `__eq__` _(перифразирам твоят въпрос)_? Това, което имаш по-горе е сравнително on-point - сортирането би следвало да стане чрез атрибутът `tone` на обектите от тип `Tone`. Тоновете ти са в списък и те не са сортирани. Сортирането става чак при репрезентацията като стринг, където е и въпросната `lambda` функция, която често се ползва по този начин за да "зададе" алгоритъм за сортиране на `sorted` метода. В случая просто взима въпросния `tone` атрибут и прави изместването, всичко от което на теория изглежда правилно. Ако решиш да дефинираш `__eq__`, ще можеш да си позволиш сортиране без тази ламбда, съответно "стандартната" употреба на `sorted` ще работи прекрасно, ако самото сравнение имплементираш в `__eq__`. Не мога на прима виста да ти кажа защо не принтира правилните стойности, а и това вече би било равнозначно на това да дебъгваме твоя код, което вече няма да е справедливо.
Екатерина Стоянова
31.10.2024 13:44

Здравейте! Извинявам се, че Ви занимавам, но реших, че това ще бъде по-добра стратегия, отколкото да използвам ChatBot-а. Качих нарочно невалидно и (очевидно) незавършено домашно, за да Ви попитам по него. Проблемът ми идва в това как кода "уж" слага отделните тонове в лист, така че да няма повторения и с (малко помощ от чат-бота), после сортирам спрямо индекс на валидните стойности, които съм дала. Въпросът ми е - тук нужно ли е да се предефинира __eq__ оператора, защото дори и когато го направих, пак при генерираните от бота тестове, принтеше грешно. Знам, че това може да се приеме като все едно ми помагате с домашното, така че разбирам, ако не ми отговорите, просто сама се обърках в собствения си код, а реално искам да разбера проблема 😭
История

f1class Tone:f1class Tone:
2    VALID_NOTES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] # list to use the indexes2    VALID_NOTES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] # list to use the indexes
33
4    def __init__(self, tone):4    def __init__(self, tone):
5        self.tone = tone5        self.tone = tone
66
7    def __str__(self):7    def __str__(self):
8        return str(self.tone)8        return str(self.tone)
99
10    def __eq__(self, other):10    def __eq__(self, other):
11        return self.VALID_NOTES.index(self.tone) == self.VALID_NOTES.index(other.tone)11        return self.VALID_NOTES.index(self.tone) == self.VALID_NOTES.index(other.tone)
1212
13    def __hash__(self):13    def __hash__(self):
14        return hash(self.tone)14        return hash(self.tone)
1515
16    def __and__(self, other): # using it for the major and minor functions for convenience16    def __and__(self, other): # using it for the major and minor functions for convenience
17        return abs(self.VALID_NOTES.index(self.tone) - self.VALID_NOTES.index(other.tone))17        return abs(self.VALID_NOTES.index(self.tone) - self.VALID_NOTES.index(other.tone))
1818
19    def __add__(self, other):19    def __add__(self, other):
20        if isinstance(other, Tone):20        if isinstance(other, Tone):
21            return Chord (self, other)21            return Chord (self, other)
22        elif isinstance(other, Interval):22        elif isinstance(other, Interval):
23            new_tone_index = (self.VALID_NOTES.index(self.tone) + other.number_of_semitones) % 1223            new_tone_index = (self.VALID_NOTES.index(self.tone) + other.number_of_semitones) % 12
24            new_tone = self.VALID_NOTES[new_tone_index]24            new_tone = self.VALID_NOTES[new_tone_index]
25            return Tone(new_tone)25            return Tone(new_tone)
26        else:26        else:
27            raise TypeError("Invalid operation")27            raise TypeError("Invalid operation")
2828
29    def __sub__(self, other):29    def __sub__(self, other):
30        if isinstance(other, Tone):30        if isinstance(other, Tone):
31            return Interval(self&other)31            return Interval(self&other)
32        elif isinstance(other, Interval):32        elif isinstance(other, Interval):
33            new_tone_index = (self.VALID_NOTES.index(self.tone) - other.number_of_semitones) % 1233            new_tone_index = (self.VALID_NOTES.index(self.tone) - other.number_of_semitones) % 12
34            new_tone = self.VALID_NOTES[new_tone_index]34            new_tone = self.VALID_NOTES[new_tone_index]
35            return Tone(new_tone)35            return Tone(new_tone)
36        else:36        else:
37            raise TypeError("Invalid operation")37            raise TypeError("Invalid operation")
3838
3939
40class Interval:40class Interval:
41    SEMITONES = {41    SEMITONES = {
42        0: "unison",42        0: "unison",
43        1: "minor 2nd",43        1: "minor 2nd",
44        2: "major 2nd",44        2: "major 2nd",
45        3: "minor 3rd",45        3: "minor 3rd",
46        4: "major 3rd",46        4: "major 3rd",
47        5: "perfect 4th",47        5: "perfect 4th",
48        6: "diminished 5th",48        6: "diminished 5th",
49        7: "perfect 5th",49        7: "perfect 5th",
50        8: "minor 6th",50        8: "minor 6th",
51        9: "major 6th",51        9: "major 6th",
52        10: "minor 7th",52        10: "minor 7th",
53        11: "major 7th"53        11: "major 7th"
54    }54    }
5555
56    def __init__(self, number_of_semitones):56    def __init__(self, number_of_semitones):
57        self.number_of_semitones = number_of_semitones % 1257        self.number_of_semitones = number_of_semitones % 12
5858
59    def __str__(self):59    def __str__(self):
60        return self.SEMITONES[self.number_of_semitones]60        return self.SEMITONES[self.number_of_semitones]
6161
62    def __add__(self, other):62    def __add__(self, other):
63        if isinstance(other, Tone):63        if isinstance(other, Tone):
64            raise TypeError ("Invalid operation")64            raise TypeError ("Invalid operation")
65        elif isinstance(other, Interval):65        elif isinstance(other, Interval):
66            return Interval(self.number_of_semitones + other.number_of_semitones)66            return Interval(self.number_of_semitones + other.number_of_semitones)
6767
68    def __neg__(self):68    def __neg__(self):
69        return Interval(-self.number_of_semitones)69        return Interval(-self.number_of_semitones)
7070
tt71 
71class Chord:72class Chord:
72    CHROMATIC_SCALE = Tone.VALID_NOTES73    CHROMATIC_SCALE = Tone.VALID_NOTES
7374
74    def __init__(self, main_tone, *tones):75    def __init__(self, main_tone, *tones):
75        self.main_tone = main_tone76        self.main_tone = main_tone
76        #remove duplicates by first using a set and then back to a list77        #remove duplicates by first using a set and then back to a list
77        unique_tones = list(set(tones) | {main_tone})78        unique_tones = list(set(tones) | {main_tone})
78        if len(unique_tones) < 2:79        if len(unique_tones) < 2:
79            raise TypeError("Cannot have a chord made of only 1 unique tone")80            raise TypeError("Cannot have a chord made of only 1 unique tone")
80        self.tones = unique_tones81        self.tones = unique_tones
8182
82    def __str__(self):83    def __str__(self):
83        to_return = str(self.main_tone)84        to_return = str(self.main_tone)
84        main_tone_idx = self.CHROMATIC_SCALE.index(to_return)85        main_tone_idx = self.CHROMATIC_SCALE.index(to_return)
85        tone_str = {str(tone) for tone in self.tones}86        tone_str = {str(tone) for tone in self.tones}
86        # sorting based on the main tone, NOT based on the indexation in Valid_Tones87        # sorting based on the main tone, NOT based on the indexation in Valid_Tones
87        for tone in Tone.VALID_NOTES[main_tone_idx + 1:]:88        for tone in Tone.VALID_NOTES[main_tone_idx + 1:]:
88            if tone in tone_str:89            if tone in tone_str:
89                to_return += "-" + tone90                to_return += "-" + tone
90        for tone in Tone.VALID_NOTES[:main_tone_idx]:91        for tone in Tone.VALID_NOTES[:main_tone_idx]:
91            if tone in tone_str:92            if tone in tone_str:
92                to_return += "-" + tone93                to_return += "-" + tone
93        return to_return94        return to_return
9495
95    def is_minor(self):96    def is_minor(self):
96        for t in self.tones:97        for t in self.tones:
97            if self.main_tone != t and (self.main_tone & t) == 3:  # 3 is equal to the index of minor 3rd98            if self.main_tone != t and (self.main_tone & t) == 3:  # 3 is equal to the index of minor 3rd
98                return True99                return True
99        return False100        return False
100101
101    def is_major(self):102    def is_major(self):
102        for t in self.tones:103        for t in self.tones:
103            if self.main_tone != t and (self.main_tone & t) == 4:  # 4 is equal to the index of major 3rd104            if self.main_tone != t and (self.main_tone & t) == 4:  # 4 is equal to the index of major 3rd
104                return True105                return True
105        return False106        return False
106107
107    def is_power_chord(self):108    def is_power_chord(self):
108        is_it_minor = self.is_minor()109        is_it_minor = self.is_minor()
109        is_it_major = self.is_major()110        is_it_major = self.is_major()
110        return not (is_it_major or is_it_minor)111        return not (is_it_major or is_it_minor)
111112
112    def __add__(self, other):113    def __add__(self, other):
113        if isinstance(other, Tone):114        if isinstance(other, Tone):
114            return Chord(self.main_tone, *(self.tones + [other]))115            return Chord(self.main_tone, *(self.tones + [other]))
115        elif isinstance(other, Chord):116        elif isinstance(other, Chord):
116            return Chord(self.main_tone, *(self.tones+other.tones))117            return Chord(self.main_tone, *(self.tones+other.tones))
117118
118    def __sub__(self, other):119    def __sub__(self, other):
119        if isinstance(other, Tone) and other in self.tones:120        if isinstance(other, Tone) and other in self.tones:
120            if len(self.tones) >= 3:121            if len(self.tones) >= 3:
121                other_index = self.tones.index(other)122                other_index = self.tones.index(other)
122                return Chord(self.main_tone, *(self.tones[other_index + 1:] + self.tones[:other_index]))123                return Chord(self.main_tone, *(self.tones[other_index + 1:] + self.tones[:other_index]))
123            else:124            else:
124                raise TypeError("Cannot have a chord made of only 1 unique tone")125                raise TypeError("Cannot have a chord made of only 1 unique tone")
125        else:126        else:
126            raise TypeError(f"Cannot remove tone {other} from chord {self}")127            raise TypeError(f"Cannot remove tone {other} from chord {self}")
127128
128    def transposed(self, interval):129    def transposed(self, interval):
129        to_transpose = list()130        to_transpose = list()
130        to_transpose.append(self.main_tone+interval)131        to_transpose.append(self.main_tone+interval)
131        for t in self.tones:132        for t in self.tones:
132            to_transpose.append(t + interval)133            to_transpose.append(t + interval)
133        return Chord(*to_transpose)134        return Chord(*to_transpose)
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1class Tone:f1class Tone:
n2    VALID_NOTES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] #arr to use the indexesn2    VALID_NOTES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] # list to use the indexes
33
4    def __init__(self, tone):4    def __init__(self, tone):
n5        if tone not in self.VALID_NOTES:n
6            raise TypeError("nqkakuv text lol")
7        self.tone = tone5        self.tone = tone
86
9    def __str__(self):7    def __str__(self):
n10        return self.tonen8        return str(self.tone)
9 
10    def __eq__(self, other):
11        return self.VALID_NOTES.index(self.tone) == self.VALID_NOTES.index(other.tone)
12 
13    def __hash__(self):
14        return hash(self.tone)
15 
16    def __and__(self, other): # using it for the major and minor functions for convenience
17        return abs(self.VALID_NOTES.index(self.tone) - self.VALID_NOTES.index(other.tone))
18 
19    def __add__(self, other):
20        if isinstance(other, Tone):
21            return Chord (self, other)
22        elif isinstance(other, Interval):
23            new_tone_index = (self.VALID_NOTES.index(self.tone) + other.number_of_semitones) % 12
24            new_tone = self.VALID_NOTES[new_tone_index]
25            return Tone(new_tone)
26        else:
27            raise TypeError("Invalid operation")
28 
29    def __sub__(self, other):
30        if isinstance(other, Tone):
31            return Interval(self&other)
32        elif isinstance(other, Interval):
33            new_tone_index = (self.VALID_NOTES.index(self.tone) - other.number_of_semitones) % 12
34            new_tone = self.VALID_NOTES[new_tone_index]
35            return Tone(new_tone)
36        else:
37            raise TypeError("Invalid operation")
1138
1239
13class Interval:40class Interval:
14    SEMITONES = {41    SEMITONES = {
15        0: "unison",42        0: "unison",
16        1: "minor 2nd",43        1: "minor 2nd",
17        2: "major 2nd",44        2: "major 2nd",
18        3: "minor 3rd",45        3: "minor 3rd",
19        4: "major 3rd",46        4: "major 3rd",
20        5: "perfect 4th",47        5: "perfect 4th",
21        6: "diminished 5th",48        6: "diminished 5th",
22        7: "perfect 5th",49        7: "perfect 5th",
23        8: "minor 6th",50        8: "minor 6th",
24        9: "major 6th",51        9: "major 6th",
25        10: "minor 7th",52        10: "minor 7th",
26        11: "major 7th"53        11: "major 7th"
27    }54    }
nn55 
28    def __init__(self, number_of_semitones):56    def __init__(self, number_of_semitones):
29        self.number_of_semitones = number_of_semitones % 1257        self.number_of_semitones = number_of_semitones % 12
3058
31    def __str__(self):59    def __str__(self):
32        return self.SEMITONES[self.number_of_semitones]60        return self.SEMITONES[self.number_of_semitones]
3361
nn62    def __add__(self, other):
63        if isinstance(other, Tone):
64            raise TypeError ("Invalid operation")
65        elif isinstance(other, Interval):
66            return Interval(self.number_of_semitones + other.number_of_semitones)
67 
68    def __neg__(self):
69        return Interval(-self.number_of_semitones)
3470
35class Chord:71class Chord:
36    CHROMATIC_SCALE = Tone.VALID_NOTES72    CHROMATIC_SCALE = Tone.VALID_NOTES
3773
38    def __init__(self, main_tone, *tones):74    def __init__(self, main_tone, *tones):
39        self.main_tone = main_tone75        self.main_tone = main_tone
n40        #remove duplicates by fisr using a set and then back to a listn76        #remove duplicates by first using a set and then back to a list
41        unique_tones = {main_tone} | set(tones)77        unique_tones = list(set(tones) | {main_tone})
42        if len(unique_tones) < 2:78        if len(unique_tones) < 2:
43            raise TypeError("Cannot have a chord made of only 1 unique tone")79            raise TypeError("Cannot have a chord made of only 1 unique tone")
n44        self.tones = list(unique_tones) #this way we dont have duplicates and still can sortn80        self.tones = unique_tones
4581
46    def __str__(self):82    def __str__(self):
n47        #get the index of the 'root'n83        to_return = str(self.main_tone)
48        main_tone_idx = self.CHROMATIC_SCALE.index(self.main_tone.tone)84        main_tone_idx = self.CHROMATIC_SCALE.index(to_return)
49        sorted_tones = sorted(85        tone_str = {str(tone) for tone in self.tones}
50            self.tones,86        # sorting based on the main tone, NOT based on the indexation in Valid_Tones
51            key = lambda t: (self.CHROMATIC_SCALE.index(t.tone) - main_tone_idx) % 1287        for tone in Tone.VALID_NOTES[main_tone_idx + 1:]:
52        ) #asked for help from a friend for this (aka chat-bota) :~(88            if tone in tone_str:
53        return "-".join(str(tone) for tone in sorted_tones)89                to_return += "-" + tone
90        for tone in Tone.VALID_NOTES[:main_tone_idx]:
91            if tone in tone_str:
92                to_return += "-" + tone
93        return to_return
5494
nn95    def is_minor(self):
96        for t in self.tones:
97            if self.main_tone != t and (self.main_tone & t) == 3:  # 3 is equal to the index of minor 3rd
98                return True
99        return False
55100
n56c = Tone("C")n101    def is_major(self):
57d_sharp = Tone("D#")102        for t in self.tones:
58g = Tone("G")103            if self.main_tone != t and (self.main_tone & t) == 4:  # 4 is equal to the index of major 3rd
104                return True
105        return False
59106
n60c_minor_chord = Chord(c, d_sharp, g)n107    def is_power_chord(self):
61print(str(c_minor_chord))  # Output should be "C-D#-G"108        is_it_minor = self.is_minor()
109        is_it_major = self.is_major()
110        return not (is_it_major or is_it_minor)
62111
n63c, another_c, f = Tone("C"), Tone("C"), Tone("F")n112    def __add__(self, other):
64csus4_chord = Chord(c, f, another_c)113        if isinstance(other, Tone):
65print(str(csus4_chord))  # Output should be "C-F" -> printi C-C-F114            return Chord(self.main_tone, *(self.tones + [other]))
115        elif isinstance(other, Chord):
116            return Chord(self.main_tone, *(self.tones+other.tones))
66117
n67f, c, d, a, g = Tone("F"), Tone("C"), Tone("D"), Tone("A"), Tone("G")n118    def __sub__(self, other):
68f_sixth_ninth_chord = Chord(f, c, d, a, g)119        if isinstance(other, Tone) and other in self.tones:
69print(str(f_sixth_ninth_chord))  # Output should be "F-G-A-C-D"120            if len(self.tones) >= 3:
121                other_index = self.tones.index(other)
122                return Chord(self.main_tone, *(self.tones[other_index + 1:] + self.tones[:other_index]))
123            else:
124                raise TypeError("Cannot have a chord made of only 1 unique tone")
125        else:
126            raise TypeError(f"Cannot remove tone {other} from chord {self}")
70127
tt128    def transposed(self, interval):
129        to_transpose = list()
130        to_transpose.append(self.main_tone+interval)
131        for t in self.tones:
132            to_transpose.append(t + interval)
133        return Chord(*to_transpose)
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op