0

So lets say I have a class called Car as below:

class Car(object):
    """Car example with weight and speed."""
    def __init__(self):
        self.weight = None
        self.speed = None

If I initialize a Car as an empty object:

red_car = Car()

And I add a speed and a weight:

red_car.speed = 60
red_car.weight = 3500

That's all fine but what if I want to run a function when attempting to add those variables to the instance? Like this function:

def change_weight(self, any_int):
    return (any_int - 10)

The thing is though I want it to automatically run this function whenever I attempt to add specific instance variables to the object. If possible I would like it to run change_weight only on the weight instance variable.

Am I understanding this correctly or should I just be running the integer through the function separately and then adding to the object after manually?

3
  • This seems like a perfect use case for getters and setters. Commented May 9, 2014 at 1:34
  • 1
    @GWW, Noooo. This is Python not Java Commented May 9, 2014 at 1:35
  • 1
    @gnibbler: Sorry I should have said properties Commented May 9, 2014 at 3:50

2 Answers 2

6

You want to use properties

class Car(object):
    """Car example with weight and speed."""
    def __init__(self):
        self._weight = None # internal value
        self.speed = None

    @property
    def weight(self):
        return self._weight

    @weight.setter
    def weight(self, the_weight):
        self._weight = the_weight - 10 # or whatever here

Now, you can set speed normally; when you execute car.weight = 20 the setter function will be called, and the actual weight will be set to 20 - 10 = 10.

Sign up to request clarification or add additional context in comments.

2 Comments

All this time.. so wait a sec let me see if I understand this correctly then.. You're declaring the function called weight with a decorator property but it's returning to the instance _weight (why a private value? Why not just weight? Then you have another function called weight but this has a decorator called weight.setter on it, I assume because then when I do car.weight = 20 it runs this function? And the decorator weight.setter grabs the other weight function as a return once the weight.setter function is done? For the most part it makes sense.
I just am looking for clarification that what I wrote above is correct and the whole thing about having to make it a private variable with the _.
2

Read up on Python's notion of Descriptors. In particular, it sounds like you want to define a custom __set__() method.

For example, obj.d looks up d in the dictionary of obj. If d defines the method__get__(), then d.__get__(obj) is invoked according to the precedence rules listed below.

Alternately, you may find using Properties (a specific type of Descriptor) a little easier to work with.

property() is a succinct way of building a data descriptor that triggers function calls upon access to an attribute.

The behavior of descriptors is fairly logical once you understand it, but it doesn't behave quite as you might expect; in particular, __get__() and __set__() should not be confused with getters and setters, like the Java concept. So look at some of the examples above and play around with them before diving in.

1 Comment

Interesting! Will do!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.