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.

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.

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.

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.

\[ \mathrm{BMI} = \frac{w}{h^2}\ \]
\[ \mathrm{PBF} = 1.20\, \mathrm{BMI} + 0.23 y - 10.8 s - 5.4 \]

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.

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:

  • balance

float

Initial balance of the bank account.

deposit(amount)

Deposit an amout into the account.

Parameters:

  • amount

float

Amount to deposit.

withdraw(amount)

Withdraw an amount from the account.

Parameters:

  • amount

float

Amount to withdraw.

Returns:

  • float

Amount withdrawn, 0 if not possible.

get_balance()

Return the balance of the account.

Returns:

  • float

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:

  • name

str

The name of the person wishing to register.

Returns:

  • int

1 if registration was successful, -1 otherwise.

deregister(name)

Deregistrer the user.

Parameters:

  • name

str

The name of the person wishing to deregister.

Returns:

  • int

1 if deregistration was successful, -1 otherwise.

get_num_registered()

Get the number of registered people.

Returns:

  • int

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

\[ \mu = \frac{1}{N} \sum_{i=1}^N x_i \quad\text{ and }\quad \sigma = \sqrt{\frac{1}{N-1} \sum_{i = 1}^N (x_i-\mu)^2}\,, \]

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

\[ t = \frac{\mu - \mu_0}{{\sigma}/{ \sqrt{N}}}\, \]

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:

  • samples

list[float]

List of samples.

one_sample_ttest(mu_0)

Compute one sample t-value and determine whether it is outside the expected range.

Parameters:

  • mu_0

float

Proposed mean.

Returns:

  • bool

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:

  • blocks

list[str]

A list of course block names.

  • points

list[int]

The maximum number of points allowed in course blocks.

add_course(name, block, ects)

Add a course to the study planner.

Parameters:

  • name

str

The name of the course to add.

  • block

str

The course block to add the course to.

  • ects

int

The number of ects points the course is worth.

Returns:

  • int

-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.

One possible output is shown below, but the exact format is up to you.