Skip to content

Commit 42dcf48

Browse files
Pushing final exam review
1 parent 0937f3e commit 42dcf48

File tree

5 files changed

+234
-1
lines changed

5 files changed

+234
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ resource, send me an [**email**](mailto:[email protected]) about it with the subjec
3636
20. [**Intro to Object-Oriented Programming**](lectures/oop_1/)
3737
21. [**Intro to Object-Oriented Programming: Methods and the `__str__()` Method**](lectures/oop_2/)
3838
22. [**Intro to Object-Oriented Programming: Dunder / "Magic" Methods**](lectures/oop_3/)
39+
23. [**Final Exam Review**](lectures/final_review/)
3940

4041
### How To Use This Repository
4142

@@ -76,7 +77,6 @@ That is, each [**lecture**](#Lectures) sub-folder contains a lecture notes `READ
7677
- [**Loops and Strings Practice**](practice/loops/)
7778
7879
22. [**Midterm 2 Review**](lectures/midterm_2_review/)
79-
27. [**Final Exam Review**](lectures/final_review/)
8080
28. [**Extra File IO Review**](lectures/files_review/) -->
8181

8282
---

lectures/final_review/README.md

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<h2 align=center>Lecture 27</h2>
2+
3+
<h1 align=center>Final Exam Review</h1>
4+
5+
### 13 Floréal, Year CCXXXI
6+
7+
***Song of the day***: _[**Mr. Bojangles**](https://youtu.be/LzofnHLOer4) by Nina Simone (2011)_
8+
9+
---
10+
11+
### _Eeveelutionary Theory_
12+
13+
As you may remember from the review, the Pokémon [**Eevee**](https://bulbapedia.bulbagarden.net/wiki/Eevee_(Pok%C3%A9mon)) has several type-specific [**evolutions**](https://bulbapedia.bulbagarden.net/wiki/Eeveelution). Eevee will evolve into some of these Pokémon depending on which **evolution stone** it is given. For the purposes of this problem, we'll focus on the original three Eeveelutions:
14+
15+
- **Vaporeon** (_`"water"`-type_): If Eevee is given a _Water Stone_ (`"water_stone"` in code).
16+
- **Jolteon** (_`"electric"`-type_): If Eevee is given a _Thunder Stone_ (`"thunder_stone"` in code).
17+
- **Flareon** (_`"fire"`-type_): If Eevee is given a _Fire Stone_ (`"fire_stone"` in code).
18+
19+
Define an `Eevee` class that will accept two parameters: `nickname`, a string containing the nickname given to the `Eevee` object, and `description_filepath`, a string containing the address of a `txt` file containing a short description of this specific `Eevee` object. The file, if it exists, will always look slightly different depending on
20+
the Eevee's specific stats, but it will always be of the following general format:
21+
22+
```text
23+
Eevee
24+
Nature: friendly
25+
Level: 5
26+
```
27+
28+
The `Eeevee` class will have five instance attributes:
29+
30+
- `nickname`: The nickname passed by the user.
31+
- `evol_status`: The current Eeveelutionary status of the `Eevee` object. The value of this attribute is `None` when the Eevee is un-evolved, or either `"Vaporeon"`, `"Jolteon"`, or `"Flareon"` if it has been evolved. We can assume that all newly instantiated `Eevee` objects start un-evolved.
32+
- `type`: A string containing the current type of the `Eevee` object. We can assume that all newly instantiated `Eevee` objects are of type `"normal"`.
33+
- `nature`: A string containing the nature denoted in the file. Will be `None` if file is not successfully opened.
34+
- `level`: An integer containing this object's level as denoted in the file. Will be `1` if file is not successfully opened.
35+
36+
---
37+
38+
The `Eevee` class will have three instance methods associated to it. The first `can_evolve()` (_**sig**: `str` => `bool`_), will accept one string parameter, `stone_name`, a string containing the name of the evolutionary stone that the user wishes to give to this `Eevee` object. `can_evolve()` will then return `True` **if and only if**:
39+
40+
1. The `Eevee` object is un-evolved,
41+
2. The `stone_name` is one of the three valid evolutionary stones mentioned above.
42+
43+
If either of these conditions is not met, `can_evolve()` will return `False`.
44+
45+
---
46+
47+
Next, define a method called `evolve()` (_**sig**: `str` => `None`_). `evolve()` will accept one parameter, `stone_name`, a string containing the name of the evolutionary stone that the user wishes to give to this `Eevee` object. If the `Eevee` object meets all conditions necessary to evolve, `evolve()` will update the `evol_status`
48+
and `type` of the `Eevee` object to their appropriate new values.
49+
50+
To make this a little simpler, you may assume that the following dictionary is already defined at the top of your file, which you may use if you find it useful (in other words, you **don't** have to use it if you don't find it useful):
51+
52+
```python
53+
INFO_PER_STONE = {
54+
"water_stone": {
55+
# Water stone information
56+
"eeveelution": "Vaporeon",
57+
"type": "water"
58+
},
59+
"thunder_stone": {
60+
# Thunder stone information
61+
"eeveelution": "Jolteon",
62+
"type": "electric"
63+
},
64+
"fire_stone": {
65+
# Fire stone information
66+
"eeveelution": "Flareon",
67+
"type": "fire"
68+
}
69+
}
70+
```
71+
72+
---
73+
74+
Finally, define a `get_stats()` method (_**sig**: `None` => `list`_) that will return a list of the values of all the object's non-`None` attributes. If you can, do this using list comprehension—only then will you become a Python deity.
75+
76+
---
77+
78+
Sample behaviour:
79+
80+
```python
81+
# If the file exists...
82+
camille = Eevee("Camille", "description.txt")
83+
print(camille.get_stats()) # pre-evolution
84+
85+
camille.evolve("thunder_stone")
86+
print(camille.get_stats()) # post-evolution
87+
88+
# If the file doesn't exist...
89+
fryderyk = Eevee("Fryderyk", "not_description.txt")
90+
print(fryderyk.get_stats()) # pre-evolution
91+
92+
fryderyk.evolve("fire_stone")
93+
print(fryderyk.get_stats()) # post-evolution
94+
```
95+
96+
Output:
97+
98+
```text
99+
['Camille', 'friendly', 5, 'normal']
100+
['Camille', 'Jolteon', 'friendly', 5, 'electric']
101+
['Fryderyk', 1, 'normal']
102+
['Fryderyk', 'Flareon', 1, 'fire']
103+
```
104+
105+
---
106+
107+
[**Solution**](solution/eevee.py)

lectures/final_review/description.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Eevee
2+
Nature: curious
3+
Level: 10

lectures/final_review/eevee.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
INFO_PER_STONE = {
2+
"water_stone": {
3+
# Water stone information
4+
"eeveelution": "Vaporeon",
5+
"type": "water"
6+
},
7+
"thunder_stone": {
8+
# Thunder stone information
9+
"eeveelution": "Jolteon",
10+
"type": "electric"
11+
},
12+
"fire_stone": {
13+
# Fire stone information
14+
"eeveelution": "Flareon",
15+
"type": "fire"
16+
}
17+
}
18+
19+
20+
class Eevee:
21+
pass
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
VALUE_IDX = 1
2+
INFO_PER_STONE = {
3+
"water_stone": {
4+
# Water stone information
5+
"eeveelution": "Vaporeon",
6+
"type": "water"
7+
},
8+
"thunder_stone": {
9+
# Thunder stone information
10+
"eeveelution": "Jolteon",
11+
"type": "electric"
12+
},
13+
"fire_stone": {
14+
# Fire stone information
15+
"eeveelution": "Flareon",
16+
"type": "fire"
17+
}
18+
}
19+
20+
21+
class Eevee:
22+
def __init__(self, nickname, description_filename):
23+
# These three attributes are the same for all Eevee objects, regardless of the existence of the file
24+
self.nickname = nickname
25+
self.eeveelution_status = None
26+
self.type = "normal"
27+
28+
try:
29+
file = open(description_filename, 'r')
30+
except FileNotFoundError:
31+
# If the file doesn't exist, we set the specified "default" values for the remaining parameters and return
32+
self.nature = None
33+
self.level = 5
34+
return
35+
36+
# If they file does exist...
37+
file.readline() # get rid of the header first
38+
39+
"""
40+
And extract the information in the exact same way for the remaining two lines:
41+
1. Read the line,
42+
2. Strip it to get rid of the '\n',
43+
3. Split it by spaces to separate the stat's name from its value as separate elements in a list,
44+
4. Isolate the actual value from the list, which is in index 1.
45+
"""
46+
self.nature = file.readline().strip().split()[VALUE_IDX]
47+
self.level = int(file.readline().strip().split()[VALUE_IDX]) # in the case of level, we have to cast to int
48+
49+
file.close()
50+
51+
def can_evolve(self, stone_name):
52+
"""
53+
As per the prompt, we DON'T evolve if:
54+
- eeveelution_status is None, or
55+
- stone_name is not either "water_stone", "electric_stone", or "fire_stone".
56+
"""
57+
return (not self.eeveelution_status) and (stone_name in INFO_PER_STONE)
58+
59+
def evolve(self, stone_name):
60+
# Check if Eevee can evolve first
61+
if not self.can_evolve(stone_name):
62+
return
63+
64+
"""
65+
To evolve, we simply update eeveelution_status and type to their appropriate values:
66+
- If stone_name is "water_stone", eeveelution_status will become "Vaporeon" and type will become "water".
67+
- If stone_name is "electric_stone", eeveelution_status will become "Jolteon" and type will become
68+
"electric".
69+
- If stone_name is "fire_stone", eeveelution_status will become "Flareon" and type will become "fire".
70+
"""
71+
self.eeveelution_status = INFO_PER_STONE[stone_name]["eeveelution"]
72+
self.type = INFO_PER_STONE[stone_name]["type"]
73+
74+
def get_stats(self):
75+
"""
76+
List comprehension logic:
77+
1. Give me the stat
78+
2. For every stat
79+
3. In the list of every single attribute
80+
4. If that stat is not None
81+
"""
82+
return [stat for stat in [self.nickname, self.eeveelution_status, self.nature, self.level, self.type]
83+
if stat is not None]
84+
85+
86+
def main():
87+
# If the file exists...
88+
camille = Eevee("Camille", "description.txt")
89+
print(camille.get_stats()) # Pre-evolution
90+
91+
camille.evolve("thunder_stone")
92+
print(camille.get_stats()) # Post-evolution
93+
94+
# If the file doesn't exist...
95+
fryderyk = Eevee("Fryderyk", "not_description.txt")
96+
print(fryderyk.get_stats()) # Pre-evolution
97+
98+
fryderyk.evolve("fire_stone")
99+
print(fryderyk.get_stats()) # Post-evolution
100+
101+
102+
main()

0 commit comments

Comments
 (0)