How to update child class argument to new value?

I have the following code, one parent class and one child class. Two positional arguments will be passed into the parent class and the child class inherits them. Child class contains a method, when it’s called, it should change the value of "self.B" from "B = 0" in the parent class to a new value that’s after the prompt. How do I update the f-string value of "B" in the "print" statement under "except"? Why is the value of "self.B" unchanged after I typed in a value for it?
”’

class Parent:
    def __init__(self, A: str, B = 0):
        self.A = A 
        self.B = B

class Child(Parent):
    def __init__(self, A: str, B = 0):
        super().__init__(A, B)

    def enter_prompt(self):
        while True:
           try:
               self.B = float(input('Please enter a numerical value: ')
           except ValueError:
               print(f"Item A {self.A}'s new value B {self.B} must be a numerical value, please try again!")
           else:
               break
        print(f"Item A {self.A}'s new value is {self.B}.")
        return self.A, self.B

After I run the following:

”’

P = Parent('Alpha', 0)
C = Child(P.A, P.B)
C.enter_prompt()

”’

My terminal:

Please enter a numerical value: www
Item A Alpha's new value B 0 is not a new numerical value, please try again!
Please enter a numerical value: 15.5
Item A Alpha's new value is 15.5.

”’
I thought the value of self.B would be changed to whatever value I typed in and be printed out in the string. Not sure how to fix this. Any ideas?

>Solution :

Your confusion has to do with when the ValueError exception gets raised. You seem to expect the assignment to happen first, then the exception to stop further progress. But that’s not how it works. In:

self.B = float(input('Please enter a numerical value: ')

The exception comes from the float call, which needs to be evaluated before any assignment happens (since it’s the result of that call that is assigned). When the value from input is invalid in float, no assignment happens at all.

If you want to be able to print out the invalid user input, do a separate assignment for that, before you convert it to a float:

b_str = input('Please enter a numerical value: ')
try:
    self.B = float(b_str)
except:
    print(f"Item A {self.A}'s new value B {b_str} must be a numerical value, please try again!")
else:
    break

Note that you might want to print out the repr of the value, rather than the value directly (so you’ll get quotation marks and special characters will be escaped), though it might not be necessary in this specific situation (since the user had to type the value for you to get it via input()). You can have an f-string format a value using repr by putting !r after the expression in the curly brackets:

print(f"Item A {self.A}'s new value B {b_str!r} must be a numerical value, please try again!")

Leave a Reply