1from functools import cmp_to_key
2
3
4TONES = (
5 "A",
6 "A#",
7 "B",
8 "C",
9 "C#",
10 "D",
11 "D#",
12 "E",
13 "F",
14 "F#",
15 "G",
16 "G#",
17)
18INTERVALS = [
19 "unison",
20 "minor 2nd",
21 "major 2nd",
22 "minor 3rd",
23 "major 3rd",
24 "perfect 4th",
25 "diminished 5th",
26 "perfect 5th",
27 "minor 6th",
28 "major 6th",
29 "minor 7th",
30 "major 7th",
31]
32
33
34class Tone:
35 def __init__(self, tone_literal):
36 assert tone_literal in TONES
37 self.tone_literal = tone_literal
38
39 def __str__(self):
40 return self.tone_literal
41
42 def __add__(self, other):
43 if isinstance(other, Tone):
44 return Chord(self, other)
45 elif isinstance(other, Interval):
46 return Tone(TONES[(TONES.index(self.tone_literal) + other.interval_length) % 12])
47
48 def __sub__(self, other):
49 if isinstance(other, Tone):
50 return Interval(Tone.get_tone_gap(other, self))
51 elif isinstance(other, Interval):
52 return Tone(TONES[(TONES.index(self.tone_literal) - other.interval_length) % 12])
53
54 @staticmethod
55 def get_tone_gap(a, b):
56 start_index = TONES.index(str(a))
57 end_index = TONES.index(str(b))
58 gap = 0
59 while TONES[start_index % 12] != TONES[end_index]:
60 start_index += 1
61 gap += 1
62 return gap
63
64
65class Interval:
66 def __init__(self, interval_length):
67 assert isinstance(interval_length, int)
68 self.interval_length = interval_length % 12
69
70 def __str__(self):
71 return INTERVALS[self.interval_length]
72
73 def __add__(self, other):
74 if isinstance(other, Tone):
75 raise TypeError("Invalid operation")
76 elif isinstance(other, Interval):
77 return Interval(self.interval_length + other.interval_length)
78
79 def __sub__(self, other):
80 if isinstance(other, Tone):
81 raise TypeError("Invalid operation")
82
83 def __neg__(self):
84 return Interval(-self.interval_length)
85
86
87class Chord:
88 def __init__(self, main_tone, *rest_tones):
89 if len(set([str(main_tone), *[str(tone) for tone in rest_tones]])) == 1:
90 raise TypeError("Cannot have a chord made of only 1 unique tone")
91
92 self.main_tone = main_tone
93 self.rest_tones = [Tone(tone) for tone in sorted(set([str(tone) for tone in rest_tones if str(tone) != str(
94 main_tone)]), key=cmp_to_key(lambda a, b: Tone.get_tone_gap(main_tone, Tone(a)) - Tone.get_tone_gap(main_tone, Tone(b))))]
95
96 def __str__(self):
97 return "-".join([str(self.main_tone), *[str(tone) for tone in self.rest_tones]])
98
99 def __add__(self, other):
100 if isinstance(other, Tone):
101 return Chord(self.main_tone, *self.rest_tones, other)
102 if isinstance(other, Chord):
103 return Chord(self.main_tone, *self.rest_tones, other.main_tone, *other.rest_tones)
104
105 def __sub__(self, other):
106 if isinstance(other, Tone):
107 if not any((str(tone) == str(other) for tone in [self.main_tone, *self.rest_tones])):
108 raise TypeError(f"Cannot remove tone {
109 str(other)} from chord {str(self)}")
110 return Chord(*[tone for tone in [self.main_tone, *self.rest_tones] if str(tone) != str(other)])
111
112 def transposed(self, interval):
113 assert isinstance(interval, Interval)
114 return Chord(self.main_tone + interval, *[tone + interval for tone in self.rest_tones])
115
116 def is_minor(self):
117 return any([INTERVALS[Tone.get_tone_gap(self.main_tone, tone)] == "minor 3rd" for tone in self.rest_tones])
118
119 def is_major(self):
120 return any([INTERVALS[Tone.get_tone_gap(self.main_tone, tone)] == "major 3rd" for tone in self.rest_tones])
121
122 def is_power_chord(self):
123 return not self.is_minor() and not self.is_major()
.....................................
----------------------------------------------------------------------
Ran 37 tests in 0.001s
OK
Виктор Бечев
04.11.2024 14:34Що се отнася до дължината на редовете - we don't mind either way, просто казвам да не го правиш специално заради нас.
|
Виктор Бечев
04.11.2024 14:33Това изглежда като нещо, което идва от средата / редактора.
Пуснах кода ти без каквото и да е от `typing` и проблем няма.
Разтърси се от къде идва, за да не се налага всеки път да ти оставяме коментари по темата _(а коментари ще оставяме, защото е напълно безсмислено да извършваш въпросната операция, тъй като функционално няма как да има проблем)_.
|
Димитър Фенерски
04.11.2024 14:30> Така като гледам следващият ред ти е по-дълъг от този, дори да не слагаш съобщението на нов ред, така че не е голяма драма да го оставиш.
не знам как на silence-на линтера, автоматично го форматира и постоянно се оплаква
https://ibb.co/M2xmq2X
|
Димитър Фенерски
04.11.2024 14:19@Виктор
Без `Any` каст имам ерор, иначе и мен ме дразнят.
Не открих чисто решение в нета и затова кастнах:
```
Argument of type "int" cannot be assigned to parameter "key" of type "Literal[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]" in function "__getitem__"
Type "int" is not assignable to type "Literal[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]"
"int" is not assignable to type "Literal[0]"
"int" is not assignable to type "Literal[1]"
"int" is not assignable to type "Literal[2]"
"int" is not assignable to type "Literal[3]"
"int" is not assignable to type "Literal[4]"
"int" is not assignable to type "Literal[5]"
"int" is not assignable to type "Literal[6]" [reportArgumentType]
```
|
f | 1 | from functools import cmp_to_key | f | 1 | from functools import cmp_to_key |
2 | 2 | ||||
3 | 3 | ||||
4 | TONES = ( | 4 | TONES = ( | ||
5 | "A", | 5 | "A", | ||
6 | "A#", | 6 | "A#", | ||
7 | "B", | 7 | "B", | ||
8 | "C", | 8 | "C", | ||
9 | "C#", | 9 | "C#", | ||
10 | "D", | 10 | "D", | ||
11 | "D#", | 11 | "D#", | ||
12 | "E", | 12 | "E", | ||
13 | "F", | 13 | "F", | ||
14 | "F#", | 14 | "F#", | ||
15 | "G", | 15 | "G", | ||
16 | "G#", | 16 | "G#", | ||
17 | ) | 17 | ) | ||
18 | INTERVALS = [ | 18 | INTERVALS = [ | ||
19 | "unison", | 19 | "unison", | ||
20 | "minor 2nd", | 20 | "minor 2nd", | ||
21 | "major 2nd", | 21 | "major 2nd", | ||
22 | "minor 3rd", | 22 | "minor 3rd", | ||
23 | "major 3rd", | 23 | "major 3rd", | ||
24 | "perfect 4th", | 24 | "perfect 4th", | ||
25 | "diminished 5th", | 25 | "diminished 5th", | ||
26 | "perfect 5th", | 26 | "perfect 5th", | ||
27 | "minor 6th", | 27 | "minor 6th", | ||
28 | "major 6th", | 28 | "major 6th", | ||
29 | "minor 7th", | 29 | "minor 7th", | ||
30 | "major 7th", | 30 | "major 7th", | ||
31 | ] | 31 | ] | ||
32 | 32 | ||||
33 | 33 | ||||
34 | class Tone: | 34 | class Tone: | ||
35 | def __init__(self, tone_literal): | 35 | def __init__(self, tone_literal): | ||
36 | assert tone_literal in TONES | 36 | assert tone_literal in TONES | ||
37 | self.tone_literal = tone_literal | 37 | self.tone_literal = tone_literal | ||
38 | 38 | ||||
39 | def __str__(self): | 39 | def __str__(self): | ||
40 | return self.tone_literal | 40 | return self.tone_literal | ||
41 | 41 | ||||
42 | def __add__(self, other): | 42 | def __add__(self, other): | ||
43 | if isinstance(other, Tone): | 43 | if isinstance(other, Tone): | ||
44 | return Chord(self, other) | 44 | return Chord(self, other) | ||
45 | elif isinstance(other, Interval): | 45 | elif isinstance(other, Interval): | ||
46 | return Tone(TONES[(TONES.index(self.tone_literal) + other.interval_length) % 12]) | 46 | return Tone(TONES[(TONES.index(self.tone_literal) + other.interval_length) % 12]) | ||
47 | 47 | ||||
48 | def __sub__(self, other): | 48 | def __sub__(self, other): | ||
49 | if isinstance(other, Tone): | 49 | if isinstance(other, Tone): | ||
50 | return Interval(Tone.get_tone_gap(other, self)) | 50 | return Interval(Tone.get_tone_gap(other, self)) | ||
51 | elif isinstance(other, Interval): | 51 | elif isinstance(other, Interval): | ||
52 | return Tone(TONES[(TONES.index(self.tone_literal) - other.interval_length) % 12]) | 52 | return Tone(TONES[(TONES.index(self.tone_literal) - other.interval_length) % 12]) | ||
53 | 53 | ||||
54 | @staticmethod | 54 | @staticmethod | ||
55 | def get_tone_gap(a, b): | 55 | def get_tone_gap(a, b): | ||
56 | start_index = TONES.index(str(a)) | 56 | start_index = TONES.index(str(a)) | ||
57 | end_index = TONES.index(str(b)) | 57 | end_index = TONES.index(str(b)) | ||
58 | gap = 0 | 58 | gap = 0 | ||
59 | while TONES[start_index % 12] != TONES[end_index]: | 59 | while TONES[start_index % 12] != TONES[end_index]: | ||
60 | start_index += 1 | 60 | start_index += 1 | ||
61 | gap += 1 | 61 | gap += 1 | ||
62 | return gap | 62 | return gap | ||
63 | 63 | ||||
64 | 64 | ||||
65 | class Interval: | 65 | class Interval: | ||
66 | def __init__(self, interval_length): | 66 | def __init__(self, interval_length): | ||
67 | assert isinstance(interval_length, int) | 67 | assert isinstance(interval_length, int) | ||
68 | self.interval_length = interval_length % 12 | 68 | self.interval_length = interval_length % 12 | ||
69 | 69 | ||||
70 | def __str__(self): | 70 | def __str__(self): | ||
71 | return INTERVALS[self.interval_length] | 71 | return INTERVALS[self.interval_length] | ||
72 | 72 | ||||
73 | def __add__(self, other): | 73 | def __add__(self, other): | ||
74 | if isinstance(other, Tone): | 74 | if isinstance(other, Tone): | ||
75 | raise TypeError("Invalid operation") | 75 | raise TypeError("Invalid operation") | ||
76 | elif isinstance(other, Interval): | 76 | elif isinstance(other, Interval): | ||
77 | return Interval(self.interval_length + other.interval_length) | 77 | return Interval(self.interval_length + other.interval_length) | ||
78 | 78 | ||||
79 | def __sub__(self, other): | 79 | def __sub__(self, other): | ||
80 | if isinstance(other, Tone): | 80 | if isinstance(other, Tone): | ||
81 | raise TypeError("Invalid operation") | 81 | raise TypeError("Invalid operation") | ||
82 | 82 | ||||
83 | def __neg__(self): | 83 | def __neg__(self): | ||
84 | return Interval(-self.interval_length) | 84 | return Interval(-self.interval_length) | ||
85 | 85 | ||||
86 | 86 | ||||
87 | class Chord: | 87 | class Chord: | ||
88 | def __init__(self, main_tone, *rest_tones): | 88 | def __init__(self, main_tone, *rest_tones): | ||
89 | if len(set([str(main_tone), *[str(tone) for tone in rest_tones]])) == 1: | 89 | if len(set([str(main_tone), *[str(tone) for tone in rest_tones]])) == 1: | ||
90 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 90 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
91 | 91 | ||||
92 | self.main_tone = main_tone | 92 | self.main_tone = main_tone | ||
93 | self.rest_tones = [Tone(tone) for tone in sorted(set([str(tone) for tone in rest_tones if str(tone) != str( | 93 | self.rest_tones = [Tone(tone) for tone in sorted(set([str(tone) for tone in rest_tones if str(tone) != str( | ||
94 | main_tone)]), key=cmp_to_key(lambda a, b: Tone.get_tone_gap(main_tone, Tone(a)) - Tone.get_tone_gap(main_tone, Tone(b))))] | 94 | main_tone)]), key=cmp_to_key(lambda a, b: Tone.get_tone_gap(main_tone, Tone(a)) - Tone.get_tone_gap(main_tone, Tone(b))))] | ||
95 | 95 | ||||
96 | def __str__(self): | 96 | def __str__(self): | ||
97 | return "-".join([str(self.main_tone), *[str(tone) for tone in self.rest_tones]]) | 97 | return "-".join([str(self.main_tone), *[str(tone) for tone in self.rest_tones]]) | ||
98 | 98 | ||||
99 | def __add__(self, other): | 99 | def __add__(self, other): | ||
100 | if isinstance(other, Tone): | 100 | if isinstance(other, Tone): | ||
101 | return Chord(self.main_tone, *self.rest_tones, other) | 101 | return Chord(self.main_tone, *self.rest_tones, other) | ||
102 | if isinstance(other, Chord): | 102 | if isinstance(other, Chord): | ||
103 | return Chord(self.main_tone, *self.rest_tones, other.main_tone, *other.rest_tones) | 103 | return Chord(self.main_tone, *self.rest_tones, other.main_tone, *other.rest_tones) | ||
104 | 104 | ||||
105 | def __sub__(self, other): | 105 | def __sub__(self, other): | ||
106 | if isinstance(other, Tone): | 106 | if isinstance(other, Tone): | ||
107 | if not any((str(tone) == str(other) for tone in [self.main_tone, *self.rest_tones])): | 107 | if not any((str(tone) == str(other) for tone in [self.main_tone, *self.rest_tones])): | ||
108 | raise TypeError(f"Cannot remove tone { | 108 | raise TypeError(f"Cannot remove tone { | ||
109 | str(other)} from chord {str(self)}") | 109 | str(other)} from chord {str(self)}") | ||
110 | return Chord(*[tone for tone in [self.main_tone, *self.rest_tones] if str(tone) != str(other)]) | 110 | return Chord(*[tone for tone in [self.main_tone, *self.rest_tones] if str(tone) != str(other)]) | ||
111 | 111 | ||||
112 | def transposed(self, interval): | 112 | def transposed(self, interval): | ||
113 | assert isinstance(interval, Interval) | 113 | assert isinstance(interval, Interval) | ||
114 | return Chord(self.main_tone + interval, *[tone + interval for tone in self.rest_tones]) | 114 | return Chord(self.main_tone + interval, *[tone + interval for tone in self.rest_tones]) | ||
115 | 115 | ||||
116 | def is_minor(self): | 116 | def is_minor(self): | ||
n | 117 | return any([INTERVALS[(Tone.get_tone_gap(self.main_tone, tone))] == "minor 3rd" for tone in self.rest_tones]) | n | 117 | return any([INTERVALS[Tone.get_tone_gap(self.main_tone, tone)] == "minor 3rd" for tone in self.rest_tones]) |
118 | 118 | ||||
119 | def is_major(self): | 119 | def is_major(self): | ||
t | 120 | return any([INTERVALS[(Tone.get_tone_gap(self.main_tone, tone))] == "major 3rd" for tone in self.rest_tones]) | t | 120 | return any([INTERVALS[Tone.get_tone_gap(self.main_tone, tone)] == "major 3rd" for tone in self.rest_tones]) |
121 | 121 | ||||
122 | def is_power_chord(self): | 122 | def is_power_chord(self): | ||
123 | return not self.is_minor() and not self.is_major() | 123 | return not self.is_minor() and not self.is_major() |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|
f | 1 | from functools import cmp_to_key | f | 1 | from functools import cmp_to_key |
n | 2 | from typing import Any, cast | n | ||
3 | 2 | ||||
4 | 3 | ||||
5 | TONES = ( | 4 | TONES = ( | ||
6 | "A", | 5 | "A", | ||
7 | "A#", | 6 | "A#", | ||
8 | "B", | 7 | "B", | ||
9 | "C", | 8 | "C", | ||
10 | "C#", | 9 | "C#", | ||
11 | "D", | 10 | "D", | ||
12 | "D#", | 11 | "D#", | ||
13 | "E", | 12 | "E", | ||
14 | "F", | 13 | "F", | ||
15 | "F#", | 14 | "F#", | ||
16 | "G", | 15 | "G", | ||
17 | "G#", | 16 | "G#", | ||
18 | ) | 17 | ) | ||
n | 19 | INTERVALS = dict([ | n | 18 | INTERVALS = [ |
20 | (0, "unison"), | 19 | "unison", | ||
21 | (1, "minor 2nd"), | 20 | "minor 2nd", | ||
22 | (2, "major 2nd"), | 21 | "major 2nd", | ||
23 | (3, "minor 3rd"), | 22 | "minor 3rd", | ||
24 | (4, "major 3rd"), | 23 | "major 3rd", | ||
25 | (5, "perfect 4th"), | 24 | "perfect 4th", | ||
26 | (6, "diminished 5th"), | 25 | "diminished 5th", | ||
27 | (7, "perfect 5th"), | 26 | "perfect 5th", | ||
28 | (8, "minor 6th"), | 27 | "minor 6th", | ||
29 | (9, "major 6th"), | 28 | "major 6th", | ||
30 | (10, "minor 7th"), | 29 | "minor 7th", | ||
31 | (11, "major 7th"), | 30 | "major 7th", | ||
32 | ]) | 31 | ] | ||
33 | 32 | ||||
34 | 33 | ||||
35 | class Tone: | 34 | class Tone: | ||
n | 36 | def __init__(self, rep): | n | 35 | def __init__(self, tone_literal): |
37 | assert rep in TONES | 36 | assert tone_literal in TONES | ||
38 | self.rep = rep | 37 | self.tone_literal = tone_literal | ||
39 | 38 | ||||
40 | def __str__(self): | 39 | def __str__(self): | ||
n | 41 | return self.rep | n | 40 | return self.tone_literal |
42 | 41 | ||||
43 | def __add__(self, other): | 42 | def __add__(self, other): | ||
44 | if isinstance(other, Tone): | 43 | if isinstance(other, Tone): | ||
45 | return Chord(self, other) | 44 | return Chord(self, other) | ||
46 | elif isinstance(other, Interval): | 45 | elif isinstance(other, Interval): | ||
n | 47 | return Tone(TONES[(TONES.index(self.rep) + other.rep) % 12]) | n | 46 | return Tone(TONES[(TONES.index(self.tone_literal) + other.interval_length) % 12]) |
48 | 47 | ||||
49 | def __sub__(self, other): | 48 | def __sub__(self, other): | ||
50 | if isinstance(other, Tone): | 49 | if isinstance(other, Tone): | ||
51 | return Interval(Tone.get_tone_gap(other, self)) | 50 | return Interval(Tone.get_tone_gap(other, self)) | ||
52 | elif isinstance(other, Interval): | 51 | elif isinstance(other, Interval): | ||
n | 53 | return Tone(TONES[(TONES.index(self.rep) - other.rep) % 12]) | n | 52 | return Tone(TONES[(TONES.index(self.tone_literal) - other.interval_length) % 12]) |
54 | 53 | ||||
55 | @staticmethod | 54 | @staticmethod | ||
56 | def get_tone_gap(a, b): | 55 | def get_tone_gap(a, b): | ||
57 | start_index = TONES.index(str(a)) | 56 | start_index = TONES.index(str(a)) | ||
58 | end_index = TONES.index(str(b)) | 57 | end_index = TONES.index(str(b)) | ||
59 | gap = 0 | 58 | gap = 0 | ||
60 | while TONES[start_index % 12] != TONES[end_index]: | 59 | while TONES[start_index % 12] != TONES[end_index]: | ||
61 | start_index += 1 | 60 | start_index += 1 | ||
62 | gap += 1 | 61 | gap += 1 | ||
63 | return gap | 62 | return gap | ||
64 | 63 | ||||
65 | 64 | ||||
66 | class Interval: | 65 | class Interval: | ||
n | 67 | def __init__(self, rep): | n | 66 | def __init__(self, interval_length): |
68 | normalized_rep = rep % 12 | 67 | assert isinstance(interval_length, int) | ||
69 | assert normalized_rep in INTERVALS | 68 | self.interval_length = interval_length % 12 | ||
70 | self.rep = normalized_rep | ||||
71 | 69 | ||||
72 | def __str__(self): | 70 | def __str__(self): | ||
n | 73 | return INTERVALS[self.rep] | n | 71 | return INTERVALS[self.interval_length] |
74 | 72 | ||||
75 | def __add__(self, other): | 73 | def __add__(self, other): | ||
76 | if isinstance(other, Tone): | 74 | if isinstance(other, Tone): | ||
77 | raise TypeError("Invalid operation") | 75 | raise TypeError("Invalid operation") | ||
78 | elif isinstance(other, Interval): | 76 | elif isinstance(other, Interval): | ||
n | 79 | return Interval(self.rep + other.rep) | n | 77 | return Interval(self.interval_length + other.interval_length) |
80 | 78 | ||||
81 | def __sub__(self, other): | 79 | def __sub__(self, other): | ||
82 | if isinstance(other, Tone): | 80 | if isinstance(other, Tone): | ||
83 | raise TypeError("Invalid operation") | 81 | raise TypeError("Invalid operation") | ||
84 | 82 | ||||
85 | def __neg__(self): | 83 | def __neg__(self): | ||
n | 86 | return Interval(-self.rep) | n | 84 | return Interval(-self.interval_length) |
87 | 85 | ||||
88 | 86 | ||||
89 | class Chord: | 87 | class Chord: | ||
90 | def __init__(self, main_tone, *rest_tones): | 88 | def __init__(self, main_tone, *rest_tones): | ||
n | 91 | if len(set([str(main_tone), *[str(tone) | n | 89 | if len(set([str(main_tone), *[str(tone) for tone in rest_tones]])) == 1: |
92 | for tone in rest_tones]])) == 1: | ||||
93 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 90 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
94 | 91 | ||||
95 | self.main_tone = main_tone | 92 | self.main_tone = main_tone | ||
n | 96 | self.rest_tones = [Tone(tone) for tone in sorted(set([str(tone) for tone in rest_tones if str(tone) != str(main_tone)]), key=cmp_to_key( | n | 93 | self.rest_tones = [Tone(tone) for tone in sorted(set([str(tone) for tone in rest_tones if str(tone) != str( |
97 | lambda a, b: Tone.get_tone_gap(main_tone, Tone(a)) - Tone.get_tone_gap(main_tone, Tone(b))))] | 94 | main_tone)]), key=cmp_to_key(lambda a, b: Tone.get_tone_gap(main_tone, Tone(a)) - Tone.get_tone_gap(main_tone, Tone(b))))] | ||
98 | 95 | ||||
99 | def __str__(self): | 96 | def __str__(self): | ||
100 | return "-".join([str(self.main_tone), *[str(tone) for tone in self.rest_tones]]) | 97 | return "-".join([str(self.main_tone), *[str(tone) for tone in self.rest_tones]]) | ||
101 | 98 | ||||
102 | def __add__(self, other): | 99 | def __add__(self, other): | ||
103 | if isinstance(other, Tone): | 100 | if isinstance(other, Tone): | ||
104 | return Chord(self.main_tone, *self.rest_tones, other) | 101 | return Chord(self.main_tone, *self.rest_tones, other) | ||
105 | if isinstance(other, Chord): | 102 | if isinstance(other, Chord): | ||
106 | return Chord(self.main_tone, *self.rest_tones, other.main_tone, *other.rest_tones) | 103 | return Chord(self.main_tone, *self.rest_tones, other.main_tone, *other.rest_tones) | ||
107 | 104 | ||||
108 | def __sub__(self, other): | 105 | def __sub__(self, other): | ||
109 | if isinstance(other, Tone): | 106 | if isinstance(other, Tone): | ||
110 | if not any((str(tone) == str(other) for tone in [self.main_tone, *self.rest_tones])): | 107 | if not any((str(tone) == str(other) for tone in [self.main_tone, *self.rest_tones])): | ||
111 | raise TypeError(f"Cannot remove tone { | 108 | raise TypeError(f"Cannot remove tone { | ||
112 | str(other)} from chord {str(self)}") | 109 | str(other)} from chord {str(self)}") | ||
n | 113 | if len(self.rest_tones) == 1: | n | 110 | return Chord(*[tone for tone in [self.main_tone, *self.rest_tones] if str(tone) != str(other)]) |
114 | raise TypeError( | ||||
115 | "Cannot have a chord made of only 1 unique tone") | ||||
116 | return Chord(*list(filter(lambda tone: str(tone) != str(other), [self.main_tone, *self.rest_tones]))) | ||||
117 | 111 | ||||
118 | def transposed(self, interval): | 112 | def transposed(self, interval): | ||
119 | assert isinstance(interval, Interval) | 113 | assert isinstance(interval, Interval) | ||
120 | return Chord(self.main_tone + interval, *[tone + interval for tone in self.rest_tones]) | 114 | return Chord(self.main_tone + interval, *[tone + interval for tone in self.rest_tones]) | ||
121 | 115 | ||||
122 | def is_minor(self): | 116 | def is_minor(self): | ||
n | 123 | return any([INTERVALS[cast(Any, Tone.get_tone_gap(self.main_tone, tone))] == "minor 3rd" for tone in self.rest_tones]) | n | 117 | return any([INTERVALS[(Tone.get_tone_gap(self.main_tone, tone))] == "minor 3rd" for tone in self.rest_tones]) |
124 | 118 | ||||
125 | def is_major(self): | 119 | def is_major(self): | ||
t | 126 | return any([INTERVALS[cast(Any, Tone.get_tone_gap(self.main_tone, tone))] == "major 3rd" for tone in self.rest_tones]) | t | 120 | return any([INTERVALS[(Tone.get_tone_gap(self.main_tone, tone))] == "major 3rd" for tone in self.rest_tones]) |
127 | 121 | ||||
128 | def is_power_chord(self): | 122 | def is_power_chord(self): | ||
129 | return not self.is_minor() and not self.is_major() | 123 | return not self.is_minor() and not self.is_major() |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|