Feedback on "Electric Bill"

Here is some unprompted feedback on the new concept exercise on Numbers.


The tests still refer to LocomotiveEngineer.

def get_kW_value(watts):
   """Return the kW value of a given watt value.
   :param: watts: int - watt value.
   :return: float - kW value.
   """

I’d change value to amount here, because the former is also associated with money, which is actually in play in this exercise.

def get_kwh_value(watts):
   """Return the kWh value of a given watt value and hours.

   :param: watts: int - watt value.
   :param: hours: int - kilowatt hour value.
   """
   pass

This one confuses me.

  • Two parameters are documented but only one is given.
  • No return value is documented.
  • What does value mean here? If monetary, a conversion factor parameter is missing. If not monetary, then I guess the second :param: should be :return:, but that makes no sense as Watts are inconvertible to kilowatthours: they are as different from each other as meters per second (speed) and miles (distance).
def get_cost(watts, power_factor, price):
   """Calculate the cost of a given kWh value, efficiency and price.

   :param: watts: int - watt value.
   :param: power_factor: float - efficiency.
   :param: price: float - price of kWh.
   :return: float - cost of kWh.
   """

I have similar problems here. Should I calculate the price per unit of energy (e.g. 1 kWh) or per unit of time? It looks like the latter: otherwise it would just be price. But then which unit of time? I guess per hour. watts probably represents used power, so the bought power should be watts / efficiency. I convert that to kW to be able to divide it by price (which is per kWh) and get a cost per hour. I should be done now, but according to the tests I am wildly off.


I did not look at the concept node content, only this exercise.

Thanks for your feedback!

Yes, that will be fixed

I will think about it.

It is only suppose to take watts, that docstring should not be there, that will be fixed.

I had a feeling this exercise could be a bit confusing. Although the instructions are very clear in what you should do.

What is confusing is perhaps that ohh we are supposed to get kWh. But we aren’t given a unit of time. The thing we don’t mention which I think could make it even more confusing is that watts is a unit of time. Watt is Joul divided by a second. Since it is a unit of time we can convert w to Wh(watt hour) by dividing it by 3600.

And the point of the exercise is that you get w used for x amount of time and are supposed to convert that to kWh. But since I mentioned time doesn’t matter in these calculations when we are only wanting to know total kWh. And the “price” given is $/kWh

So if we have x * kWh and then $/kWh and multiply those with each other. We will see that kWh disappear and we will be left with only x with a dollar value.

But again, we more or less say exactly what you are suppose to do in the instructions.

Units of time are seconds, years, etc. The word you’re looking for is rate.

We cannot. Even more confusingly, kWh is not a rate! Instead, it is the total amount of energie delivered by a 1 W source over 1 hour. That is, 1 kWh is exactly 3.6 megajoules. (proof)

I think the adoption of the Watt (1882–1908) was a mistake. Many times every single day things go wrong because of this specific instance of bad naming. We could avoid it by using Joules instead.

As I said you can do that. Watt is energy divided by a unit of time. Alright say I have 5000J/s, I can take 5000/3600 and get ish 1.38J/s * 3600. Alright and there we have Wh because it is a watt value multiplied by an hour value.

I know W = J/s. The problem is with Wh: it is not a rate and so certainly not Joules per hour.

  • 1 Wh (Watt-hour) = 3.6 kJ
  • 1 kWh (kilowatt-hour) = 3.6 MJ

Wh is watt multipled by an hour
Like this: (1.38J/s) * 3600

(1.38 J / s) × (3600 s) = (1.38 × 3600) J.

1.38 Watt * 1 hour

I mean the calculations still give a correct result. And we don’t want joules in the calculation so.

If this was a practice exercise it would have been done different, but it couldn’t be too complicated since it is a concept exercise. So there are some calculations you perhaps wouldn’t really do in real life.

I think the best way to go about this is that you may suggest some feedback on how we could improve the wording/logic.

I might submit a PR then.

Below I annotated the exemplar solution with units of all subexpressions. There are two unknowns and probably several (variously sensible) possible disambiguations. I took out the docs on purpose: reasoning about units is already difficult anough when not accompanied by intentions.

def get_kW_amount(watts):  # W → kW
    return round(
        watts  # W
        / 
        1000  # (scalar)
        , 1)


def get_kwh_amount(watts):  # W → ?x?
    return ( 
        get_kW_amount(  # W → kW
            watts       # W
        )               # kW
        // 
        3600            # s
    )                   # ?x? (kW/s or kW/h or ...
                        #      Certainly not kWh because the dimensions are wrong.)


def get_efficiency(power_factor):  # scalar → scalar
    ...

def get_cost(watts, power_factor, price):  # (W, scalar, € / ?y?) → € / (?y? / ?x?)
    return (
        price  # € / ?y?
        * (
            get_kwh_amount(  # W → ?x?
                watts        # W
            )                # ?x?
            / 
            get_efficiency(   # scalar → scalar
                power_factor  # scalar
            )                 # scalar
        )  # ?x?
    )  # € / (?y? / ?x?)
1 Like

It would be nice to fix the function names so that linters don’t complain about invalid names :slight_smile:

This would also make the function names more consistent.

Hi Isaac, I am a bit unsure of what you mean.
We changed the function names earlier (following the changes mentioned above).
Therefore the linter could complain that your solution uses the “old” function names.

Otherwise if not, so would it help me if you send the liniters message or give some example on how we could fix the function name/names.

» pylint electric_bill.py
electric_bill.py:9:0: C0103: Function name "get_kW_amount" doesn't conform to snake_case naming style (invalid-name)

get_kW_amount and get_kwh_amount have inconsistent “spellings” for “watts”.

Ahh, we use a capital letter for W in get_kW_amount, and that is not snake_case.

The correct unit is a capital letter W, although to conform with snake_case that should probably be lower case.

Thanks for notifying me about this. I will fix it.

Probably make the linter conform to the proper naming for the problem domain being solved, rather than the other way around. I think it may be less important here, but changing a B to a b, as an example, changes the value to a byte to a bit.

The language and linter is here to serve us, not the other way around, so definitely prefer for clarity of communication, rather than strict conformance to some linter.

1 Like

Yeah, well we can go the other way around aswell, changing the smal w in kwh to a capital

My vote is to follow the linter and use a lowercase w. Conventions cease being conventions if you ignore them when they can just as easily be followed. I like keeping my code linter-compliant and would prefer not to have random exercises fail the linter.

That said, the two should certainly be consistent.

I agree about not having the linter fail, ever. That said, there are times when the style guide is that, a guide, or a convention. Knowing when to deviate for clarity is one of those skills.

Here, I think that “w” vs “W” is not numerically changing the meaning, and so either way works, while “go with the default linting convention” is sound and has more value.

Don’t let the linter fail, though, definitely sound advice. If it fails, then we have only communicated half way, not good enough.

Would give some feedback as well.

  1. There’s an error in PEMDAS section.
# In the following example, the `**` operator has the highest priority, then `*`, then `+`
# Meaning we first do 4 ** 4, then 3 * 64, then 2 + 192
>>> 2 + 3 * 4 ** 4
770

There should be 3 * 256 and 2 + 768

  1. Why in get_kwh_amount function we need to cast to int resulting in inaccurate results in conversion and in get_cost function leading to zero cost in some instances.
  2. In general get_kwh_amount is really confusing in only taking watts amount and not asking for the duration.

Will fix that

The problem isn’t supposed to be super realistic instead focusing on dealing with numbers in python. As far as I am aware is there no situation in physics where you would floor divide. The point is more about following the instructions than knowing beforehand how to solve it.

We have already received ish this feedback earlier in the thread, I can give an explanation how it gets how it works. Although if there is more feedback like this, it may have to be deeper looked at.