3

I have a class function that takes 4 arguments, all class member variables in practice. Usually only one of these arguments is modified at a time and the rest of the time the would-be defaults (current values of the class member variables) are passed to the function/written out even though they aren't changing.

I thought the best would be to make these class member variables the defaults, but I'm having a hard time getting the best syntax. The following code produces behavior I desire - using a class member variable as a default parameter to a function. But it's ugly:

class test:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def testfunc(self, param = None):
        if not param:
            param = self.a
        print(param)


if __name__ == '__main__':
    a1 = test(1, 3)
    a1.testfunc()
    a2 = test(5, 5)
    a2.testfunc()
   #(prints 1 and 5 when called)

I would like to use the following:

    def testfunc(self, param = self.a):
        print(param)

But this gives the error:

NameError: name 'self' is not defined

What's a better way to do this?

5
  • 1
    The best way to do this is param=None then if param is None: (note testing by identity not equality) param = self.a Why do you think it's "ugly"? Commented Jul 22, 2015 at 16:20
  • That's really the best you can do. Default parameters like param=[] face the same issue, sadly. Commented Jul 22, 2015 at 16:20
  • @Mauris thanks for the quick confirmation. Commented Jul 22, 2015 at 16:21
  • @jonrsharpe because I will have 4 lines (param1, param2....) Commented Jul 22, 2015 at 16:21
  • You could have one line each if you used **kwargs instead, e.g. a = kwargs.get('a', self.a). Commented Jul 22, 2015 at 16:23

2 Answers 2

4

Your first attempt is pythonic, the only thing I would change is the test:

 def testfunc(self, param = None):
        if param is None:
            param = self.a
        print(param)

The problem with testing for False is that zero and an empty container (including an empty string) all resolve to False.

If you have a large number of these, see Understanding kwargs in Python

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

Comments

0

If your function takes 4 arguments, and all 4 are optional and have matching properties on the object itself, then you can make this simpler by using keyword arguments:

def testfunc(self, **kwargs):
    a, b, c, d = [kwargs.get(name, getattr(self, name)
                  for name in ('a', 'b', 'c', 'd')]

You'd then need to call this using keyword arguments:

obj.testfunc()  # all values are defaults
obj.testfunc(a=1)  # a=1, all other values are defaults
obj.testfunc(b=2, d=5)  # etc.

Comments

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.