1
class car(object):
    def read_spec_and_populate_db():
        spec = read_from_file(spec.yaml)
        populate_db(spec)

class awd(car):
    super(awd, self).read_spec_and_populate_db()

    def foo(self):
    ...

class fwd(car):
    super(fwd, self).read_spec_and_populate_db()

    def bar(self):
    ...

Class awd and fwd can be instantiated at different times or only one of them can be instantiated. Now, is there a way to restrict the base class method read_spec_and_populate_db() to be executed only once?

I did lookup in SO and found here. Wanted to see if there are any other option.

Edit: Not that I'm against it. I'm looking for ideas apart from using a flag. My current implementation is using a flag in the class.

Community
  • 1
  • 1
iobelix
  • 1,143
  • 1
  • 10
  • 16

3 Answers3

2

Just use a flag:

class car(object):
    db_read = False
    def read_spec_and_populate_db():
        if not car.db_read:
            spec = read_from_file(spec.yaml)
            populate_db(spec)
            car.db_read = True

Now you can call read_spec_and_populate_db() as many times as you want. It does its work only once.

Mike Müller
  • 82,630
  • 20
  • 166
  • 161
  • And to explain: You'll have to keep track of "it has been read" some way, and a flag is a perfectly clear way to communicate exactly that. Don't do magic stuff just for the magic. – MatsLindh Mar 30 '16 at 22:05
  • this is fine, except that a class method is cleaner IMO, no? If yes, update your answer and I'll delete mine. I've already upvoted yours – DevLounge Mar 30 '16 at 22:16
  • A classmethod does not work with inheritance. When you make an instance of `awk` first it creates `awk.populated = True`. Then when you make an instance of `car`, `car.populated` is still false and the specs will be read a second time. – Mike Müller Mar 30 '16 at 22:28
  • Oh, really? So the scope of class level variables is only the one of its direct instances? Wow, didn't know that! – DevLounge Mar 30 '16 at 22:36
0

You can use a boolean class attribute flag to keep track of whether the method has been run already or not, like so:

class Car(object):
    _populated_db = False

    def read_spec_and_populate_db(self):
        if not self._populated_db:
            spec = read_from_file(spec.yaml)
            populate_db(spec)
            self._populated_db = True
s16h
  • 4,647
  • 1
  • 21
  • 33
-1

One thought might be reassigning the name read_spec_and_populate_db, as the last step in its execution, to point to a method with the same signature but does nothing

class car(object):
    def _dummy(self):
        pass

    def read_spec_and_populate_db(self):
        spec = read_from_file(spec.yaml)
        populate_db(spec)

        self.read_spec_and_populate_db = self._dummy
0xcurb
  • 116
  • 6