Why can't I call the functions within the class?

Question:

I just started Python OOP. I have to build a simple class and function, but I don’t understand why it works in one case, but doesn’t in the other.

class Digital_signal_information:
    def __init__(self, signal_power: float, noise_power: float, n_bit_mod: int):
        self.signal_power = signal_power
        self.noise_power = noise_power
        self.n_bit_mod = n_bit_mod

class Line:
    def __init__(self,loss_coefficient: float, length: int):
        self.loss_coefficient = loss_coefficient
        self.length = length
    
    def Loss(self, loss):
        self.loss = loss_coefficient * length

    BPSK = Digital_signal_information(0.001, 0, 1)           
    QPSK = Digital_signal_information(0.001, 0, 2) # In these 4 cases it works fine.                           
    Eight_QAM = Digital_signal_information(0.001, 0, 3)    
    Sixteen_QAM = Digital_signal_information(0.001, 0, 4) 
    

# But if I do
a = Line(1.0, 2);
# and try to call a.Loss, nothing is shown.

In the exercise I have to create the Line class on which I have to use the signal_power and length attributes. I also have to use a function (or property) (correct me if I’m wrong, I’m still getting used to the OOP vocabulary). But as said, I don’t understand why it works in one part, but doesn’t in the other.

Asked By: Severjan Lici

||

Answers:

You can use @property so that the return value of the function can be directly accessed as a.Loss.

@property
def Loss(self):
    return self.loss_coefficient * self.length

# ...
a = Line(1.0,2)
print(a.Loss) # 2.0
Answered By: Unmitigated

Unmitigated has already found out to use property. However, if your loss value is not designed to change over time (in other words, the Line object is designed to be immutable), you can also use functools.cached_property. This behaves in the same way as property, but with one difference: it saves the first calculated value and all following times returns the saved one instead of calculating a new one.

The code remains almost the same as Unmitigated‘s code:

from functools import cached_property

class Digital_signal_information:
    def __init__(self, signal_power: float, noise_power: float, n_bit_mod: int):
        self.signal_power = signal_power
        self.noise_power = noise_power
        self.n_bit_mod = n_bit_mod

class Line:
    def __init__(self, loss_coefficient: float, length: int):
        self.loss_coefficient = loss_coefficient
        self.length = length
    @cached_property
    def Loss(self):
        return self.loss_coefficient * self.length

    BPSK=Digital_signal_information(0.001, 0, 1)           
    QPSK = Digital_signal_information(0.001, 0, 2)       #basically in these 4 cases I have no problem                            
    Eight_QAM = Digital_signal_information(0.001, 0, 3)    
    Sixteen_QAM = Digital_signal_information(0.001, 0, 4) 
    

#but if I do
a = Line(1.0, 2)

print(a.Loss)
#and when I try to see if I can call a.Loss it shows nothing

You should not use this when the Line object is intended to change over time. For example, the following code has an incorrect output:

print(a.Loss) # correct
a.length = 3
print(a.Loss) # not correct

Still some final remarks on your code:

  • It is better to add spaces around operators and after commas. This makes your code more readable and allows you to change your code easier later on.
  • In contrast to many other programming languages, python doesn’t require semicolons (;) to seperate lines. It is thus useless to add one.
Answered By: The_spider
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.