1

this question is not a duplicate of the other overloading question because I am attempting to reference self.args in the function. The answer given in that question does not satisfy, since if I implement that answer, I will get an error. However, in other languages, this is easily done through method overloading...so this question is highly related to the other question.

So I have a method,

class learner():
      def train(a ton of arguments):
            self.argA = argA, 
            etc.

And I want to call train with just one value, and have it use all the self calls to populate the other arguments...but it is a circular reference that python doesn't seem to support. Ideally, I would write:

class learner():
    def train(self, position, data = self.data, alpha = self.alpha, beta = etc):
          ...do a bunch of stuff

    def roll_forward(self,position):
          self.alpha += 1
          self.beta += 1
          self.train(position)

How would I do this? In other languages, I could just define a second train function that accessed the internal variables...

currently, I have a janky hack where I do this:

class learner():
     def train(...):
             ....
     def train_as_is(self,position):
         self.train(position,self.alpha,self.beta, etc.)

But this is a pretty big class, and a ton of functions like that are turning my code into spaghetti...

Chris
  • 28,822
  • 27
  • 83
  • 158
  • Possible duplicate of [How do I use method overloading in Python?](http://stackoverflow.com/questions/10202938/how-do-i-use-method-overloading-in-python) – Tamas Hegedus Dec 12 '15 at 17:42
  • No, not a duplicate. I actually went to that question for my answer. Not sure you understand what I am trying to do. – Chris Dec 12 '15 at 17:43
  • Parameter defaults get evaluated at module load time. So even if you didn't have the problem of self reference then the code wouldn't do what you intended because the modification of `self.alpha` would not affect the default value of `train()`. – NEOatNHNG Dec 12 '15 at 17:59

3 Answers3

6

An enhancement on other answers is to use a defaults dictionary:

def train(self, position, **kwargs):
    defaults = {
        'a': self.a,
        'b': self.b,
         ...etc...
    }
    defaults.update(kwargs)
    ... do something with defaults

def roll_forward(self,position):
      self.alpha += 1
      self.beta += 1
      self.train(position)
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • I like this one. Thanks dude. – Chris Dec 12 '15 at 17:56
  • this have the risk that you can call it with a extra keyword argument that is not expect... – Copperfield Dec 12 '15 at 17:59
  • true. going to think about it. – Chris Dec 12 '15 at 18:12
  • Wound up implementing an `init_and_train()` function that takes all the arguments optionally, with their default values set...and a `train()` function that takes the primary input and a dictionary...the dictionary is checked by the class for content to update the self values, so risk is mitigated. Thanks for pointing that out. – Chris Dec 12 '15 at 18:26
4

Not sure if I follow your question 100% but usual pattern is to use None as a default value:

class Foo(object):
    def __init__(self):
        self.a = ...
        self.b = ...
        ...

    def foo(self, position, a=None, b=None, ...):
        if a is None:
            a = self.a
        if b is None:
            b = self.b
        ...

You can simplify that by using or:

def foo(self, position, a=None, b=None, ...):
    a = a or self.a
    b = b or self.b
    ...

however that is not as reliable in case you will try to pass falsy values like 0 the or part will kick in

miki725
  • 27,207
  • 17
  • 105
  • 121
  • no, I didnt forget. It should be `if a is None` since you want to check when its None, you want to default `a` to whatever `self.a` is. – miki725 Dec 12 '15 at 19:26
1

you can give those parameter a default value of None, then check if any of them is None and if it is, assign the desired value like this

class learner():
    def train(self, position, data = None, alpha = None, beta = None,etc...):
        if data is None:
            data = self.data
        if alpha is None:
            alpha = self.alpha
        ...etc
        ...do a bunch of stuff
Copperfield
  • 8,131
  • 3
  • 23
  • 29