In-Class#
Coding Practice#
Code 10.1: Weather Station Revisited#
In week 8, you created a dictionary that represented a weather station, and you defined a function which took that dictionary as input and returned some processed information. You will now do something similar using classes. The advantage of using classes is that instead of having a dictionary that stores data and a function that processes that data, we can have a class that does both.
Create a class WeatherStation
. The constructor method should as input take a string with station name, and a boolean indicating whether the station is operational. These inputs should be assigned to the attributes station_name
and is_operational
. The constructor should create two additional attributes wind_readings
and temperature_readings
and assign them to an empty list. Later you will change these attributes.
Before you continue, try to create an object cph_station
of the class WeatherStation
with the name "CPH Airport Weather Station"
and operational status True
.
Check
You should be able to achieve the behavior below.
>>> cph_station = WeatherStation("Copenhagen", True)
>>> print(cph_station.station_name)
Copenhagen
>>> print(cph_station.is_operational)
True
>>> print(cph_station.wind_readings)
[]
>>> print(cph_station.temperature_readings)
[]
Add two methods to the class WeatherStation
. The first method should be named take_daily_wind_readings
and take a list of floating points as input. The method should assign the input list to the attribute wind_readings
, but only if the station is operational. If the station is not operational, the method should print a message saying that the station is not operational. The second method should be named take_daily_temperature_readings
and take a list of floating points as input. The method should assign the input list to the attribute temperature_readings
, also only if the station is operational. If the station is not operational, the method should print a message saying that the station is not operational.
Test your code.
Check
You should be able to achieve the behavior below.
>>> cph_station.take_daily_wind_readings([3.5, 6.2, 7.1, 12.1])
>>> cph_station.take_daily_temperature_readings([18.1, 18.3, 19.0, 18.5])
>>> print(cph_station.wind_readings)
[3.5, 6.2, 7.1, 12.1]
>>> print(cph_station.temperature_readings)
[18.1, 18.3, 19.0, 18.5]
Add a method get_highest_readings
to the class WeatherStation
. The method should output a tuple containing the maximum temperature reading and the maximum wind speed reading. If one or both of the readings are empty, the corresponding value in the tuple should be None
.
Test your code.
Check
You should be able to achieve the behavior below.
>>> max_wind, max_temp = cph_station.get_highest_readings()
>>> print(max_wind)
12.1
>>> print(max_temp)
19.0
Code 10.2: Health Analysis Revisited#
In this exercise we look back at Problem 2.3 Health Analysis. Recall how body mass index (BMI) and body fat percentage (BFP) are calculated from weight \(w\) in kilograms, height \(h\) in meters, age \(y\) in years.
where \(s\) is equal to \(0\) for women and \(1\) for men.
Create a class PersonHealth
. The constructor of the class should take as input the age, height, weight, and sex of the person. The age, height, and weight should be numerical values, as well as the corresponding attributes. The sex should be given to the constructor as a string, either 'm'
or 'f'
. The attribute sex
should be assigned value 1
if the input is 'm'
and 0
if the input is 'f'
.
Write a class method body_mass_index
that calculates and returns the BMI of the person.
Write a class method body_fat_percentage
that calculates and returns the body fat percentage.
Finally, write a class method get_health_description
that returns a string with an informative description of the person’s health. The string should contain the age, BMI, and BFP of the person.
Check
You should be able to achieve the behavior below.
>>> person1 = PersonHealth(20, 1.70, 69, 'f')
>>> person1.get_health_description()
'Age: 20, BMI: 23.88, BFP: 27.85'
>>> person2 = PersonHealth(61, 1.92, 91, 'm')
>>> person2.get_health_description()
'Age: 61, BMI: 24.69, BFP: 27.45'
Problem Solving#
Problem 10.3: Bank Account#
We want to create a class to represent a bank account, allowing for depositing and withdrawing money while ensuring the balance never goes negative.
Write the class definition for the class BankAccount
. The balance must be stored in an attribute called balance
. The __init__
method should take the initial balance as input. The deposit
method should take as input an amount to deposit and add it to the balance. The withdraw
method should take as input an amount to withdraw, subtract it from the balance, and return the amount withdrawn. If the withdrawal would result in a negative balance, the method should leave the balance unchanged and return 0. The get_balance
method should return the current account balance.
Here is an example of using the class.
>>> my_account = BankAccount(1000)
>>> my_account.get_balance()
1000
>>> my_account.deposit(500)
>>> my_account.get_balance()
1500
>>> my_account.withdraw(200)
200
>>> my_account.get_balance()
1300
>>> my_account.withdraw(2000)
0
>>> my_account.get_balance()
1300
In this example, the balance is 1000 initially. Then, 500 is deposited. Next, 200 is withdrawn, which is allowed since the balance before withdrawing is 1500. Finally, an attempt to withdraw 2000 is made, but since the current balance is only 1300, the withdrawal is not possible, and the balance remains unchanged. Between the deposits and withdrawals, the balance is accessed using the get_balance
method.
The filename and requirements are in the box below:
bank_account.py
BankAccount()
Class to administer a bank account enabling depositing and withdrawing.
__init__(balance)
Initialize the bank account with a balance.
Parameters:
|
|
Initial balance of the bank account. |
deposit(amount)
Deposit an amout into the account.
Parameters:
|
|
Amount to deposit. |
withdraw(amount)
Withdraw an amount from the account.
Parameters:
|
|
Amount to withdraw. |
Returns:
|
Amount withdrawn, 0 if not possible. |
get_balance()
Return the balance of the account.
Returns:
|
the balance of the bank account. |
You should also test your function with test_bank_account.py
.
Problem 10.4: Event Manager#
We want to create a class to represent an event (like a lecture or a concert), allowing for registering and de-registering participants, while preventing duplicate registrations.
Write the class definition for the class EventManager
. The class should have methods for registering, deregistering, and counting the number of registrations. The register
method should take a name as input and add it to the registrations, if the name is already among the registered it should not be added again. If the registration is successful the method should return 1 and -1 otherwise. The deregister
method should take as input a name and remove it from the registrations. If the name is not in the list it cannot be removed. If the deregistration is successful and the method should return 1 and -1 otherwise. Finally, the get_num_registered
method should return the number of participants currently registered. It is up to you to decide, how to keep track of registrations.
Here is an example of using the class.
>>> my_event = EventManager()
>>> my_event.get_num_registered()
0
>>> my_event.deregister('Mike')
-1
>>> my_event.get_num_registered()
0
>>> my_event.register('Mike')
1
>>> my_event.get_num_registered()
1
>>> my_event.register('Mike')
-1
>>> my_event.get_num_registered()
1
>>> my_event.register('John')
1
>>> my_event.get_num_registered()
2
>>> my_event.deregister('Mike')
1
>>> my_event.get_num_registered()
1
In the example, initially there are no registrations. Then, an attempt to deregister Mike is made, but this is not possible, and -1 is returned. The number of registrations is unchanged. Then, Mike is registered, and the number of registrations is 1. Then, an attempt to register Mike again is made, but this is not possible, and -1 is returned. Then, John is registered. Finally, Mike is deregistered. After each operation, the number of registrations is checked.
The filename and requirements are in the box below:
event_manager.py
EventManager()
Class to handle event registration and deregistration.
__init__()
Initialize the event with no registrations.
register(name)
Register the user as an event participant.
Parameters:
|
|
The name of the person wishing to register. |
Returns:
|
1 if registration was successful, -1 otherwise. |
deregister(name)
Deregistrer the user.
Parameters:
|
|
The name of the person wishing to deregister. |
Returns:
|
1 if deregistration was successful, -1 otherwise. |
get_num_registered()
Get the number of registered people.
Returns:
|
The number of registered people. |
You should also test your function with test_event_manager.py
.
Problem 10.5: Simple Statistics#
We want to create a class to store a sequence of numbers, and to compute some basic statistics.
Write a class definition for the class SimpleStatistics
. The constructor method should take a list of numbers as argument, and it to an attribute called samples
. The class should have get_mean
method that returns the mean of the samples, and a get_standard_deviation
method that returns the standard deviation of the samples. The mean \(\mu\) and the standard deviation \(\sigma\) should be calculated as
where \(N\) is the number samples and \(x_i\) is the value of the \(i\)th sample.
Finally, the class should have a method one_sample_ttest
that given an input value \(\mu_0\) computes the t-statistics
and returns True
if \(|t| \geq 1.96\) and False
otherwise.
Here is an example of using the class.
>>> samples = [0.1763, -1.2523, 0.9099, -0.0679, 0.1999, 0.1175, 0.143, 0.1118,
... 0.9854, -1.1836, -0.5868, 0.4839, 1.2069, 0.142, 0.2523]
>>> stat = SimpleStatistics(samples)
>>> stat.get_mean()
0.10922
>>> stat.get_standard_deviation()
0.6984926241557602
>>> stat.one_sample_ttest(0)
False
>>> stat.one_sample_ttest(0.1)
False
>>> stat.one_sample_ttest(-0.1)
False
>>> stat.one_sample_ttest(-0.25)
True
The filename and requirements are in the box below:
simple_statistics.py
SimpleStatistics()
Class to get summary statistics and compute one-sample t-test.
__init__(samples)
Initialize the statistics class with the samples.
Parameters:
|
|
List of samples. |
one_sample_ttest(mu_0)
Compute one sample t-value and determine whether it is outside the expected range.
Parameters:
|
|
Proposed mean. |
Returns:
|
True if the proposed mean is significantly different from the mean of the samples, else False. |
You should also test your function with test_one_sample_ttest.py
.
Problem 10.6: Study Planner#
In this exercise, you will create a simple study planner to manage the courses a student has registered for in each course block (e.g., foundations, directions, projects, and electives). The planner will also track the remaining ECTS available in each course block.
Define a class named StudyPlanner
. The constructor of this class should take two parameters: blocks
which is a list of strings with the names of the course blocks and points
which is a list of integers indicating the maximum number of points allowed in the corresponding blocks. The constructor should create two dictionaries as attributes. The dictionary registered_courses
has the names of the course blocks as keys and, initially, empty lists as values. The dictionary points_left
has the names of the course blocks as keys and the corresponding maximum number of points as values.
In the StudyPlanner
, define a method add_course
that as input takes three values: a string with the course name, a string with the block the course should be added to, and an integer with ECTS points. The method should verify that there are enough points left in the course block to add the course. If there are, it should add the course name to the list in registered_courses
under the specified course block and decrease the corresponding value in points_left
by the number of ECTS points for the course. The method should return 1
if the course was added successfully, and -1
if the course could not be added.
Define a method print_courses
that displays a message summarizing the registered courses and the remaining points for each course block. You may decide on the format of this message.
study_planner.py
StudyPlanner()
Study planner class to manage courses in different course groups.
__init__(blocks, points)
Initialize the study planner.
Parameters:
|
|
A list of course block names. |
|
|
The maximum number of points allowed in course blocks. |
add_course(name, block, ects)
Add a course to the study planner.
Parameters:
|
|
The name of the course to add. |
|
|
The course block to add the course to. |
|
|
The number of ects points the course is worth. |
Returns:
|
-1 if unsuccessful, 1 if successful. |
print_courses()
Print an overview of the courses in the study planner.
Test your class using the following code.
Check
Your should be able to use the class as shown below.
blocks = ['foundations', 'directions', 'projects', 'electives']
points = [55, 55, 25, 45]
planner = StudyPlanner(blocks, points)
planner.print_courses()
planner.add_course('Programming', 'foundations', 5)
planner.print_courses()
planner.add_course('Mathematics 1a', 'foundations', 10)
planner.add_course('Mathematics 1b', 'foundations', 10)
planner.add_course('Signals and systems', 'directions', 5)
planner.add_course('Optics and photonics', 'directions', 5)
planner.add_course('BSc project', 'projects', 15)
planner.add_course('Prototyping', 'projects', 10)
planner.add_course('Acoustics and noise', 'electives', 5)
planner.print_courses()
One possible output is shown below, but the exact format is up to you.
Example
---------------
BLOCK FOUNDATIONS
Points left: 30
Courses:
Programming
Mathematics 1a
Mathematics 1b
BLOCK DIRECTIONS
Points left: 45
Courses:
Signals and systems
Optics and photonics
BLOCK PROJECTS
Points left: 0
Courses:
BSc project
Prototyping
BLOCK ELECTIVES
Points left: 40
Courses:
Acoustics and noise
---------------