Home > OS >  Python - Construct Class Property - Property Decorator - Strange Behavior
Python - Construct Class Property - Property Decorator - Strange Behavior

Time:04-29

I am a newbie in object-oriented programing, and I am struggling to understand how to properly construct the property in a class objects.

I encountered an interesting behavior, and I have a hard time figuring it out.

class StepCounter:
    def __init__(self, position: int = 0):
        self.position = position

    @property
    def position(self):
        print('Getting At Work')
        return self._position * 2

    @position.setter
    def position(self, position):
        print('Setter At Work')
        if isinstance(position, int):
            self._position = position * 2
        else:
            raise ValueError('Position Argument must be an integer')

    def timer(self, value: int):
        print(value * self.position)

After constructing the property position in class object StepCounter, I did the following

# 1: set class instance. 'Setter At Work' printed.
step_instance = StepCounter(-3)

# 2: "Getting At Work" printed & returned -12. As expected.
#    -3 as input, setter multiple the input by 2, and getter multiple the value by 2 again.
print(step_instance.position)

# 3: printed -12 as expected. 
step_instance.timer(1)

However, once I mark position as a private attribute:

class StepCounter:
    def __init__(self, position: int = 0):
        self._position = position
    ....
    all other codes remain the same

I got something unexpected:

# 1: "Setter At Work" Not Printed
step_instance = StepCounter(-3)

# 2: "Getting At Work" printed & return -6
print(step_instance.position)

# 3: printed -6
step_instance.timer(1)

My questions are:

1: it seems like once I marked position as a private attribute, the setter is completely skipped. Why does such behavior show up?

2: It seems like, within setter and getter methods for a property, we often use the private attribute with the same name. such as self._position = position * 2; then if I want to mark position as private in def __init__(), what should I do?

Thank you so much for your help!

CodePudding user response:

It seems like once I marked position as a private attribute, the setter is completely skipped.

That's exactly what happens. Accessing the attribute directly does not involve the property in any way.

Only the methods of the property should access the attribute directly. __init__ (and add_number?) should go through the property like any other user of the property, unless you have a specific reason for accessing the attribute directly.

  • Related