5

I understand that in python you can set a default value for an argument like this:

 def func(self, arg='value'):
     #somecode

I have a function that will take up to 16 arguments, so I wish to store them as a tuple. The problem is I want to set default values for some values of the tuple, but not the whole thing. Would setting the default tuple as

def func(self, values=('foo', 'bar', 'foobar')):

be overriden if I passed in a tuple that only has two values? If I do, for example:

 func(('bar', 'foo')

values==('bar', 'foo'), not ('bar', 'foo', 'foobar'). Is there a workaround?

Asclepius
  • 57,944
  • 17
  • 167
  • 143
BombSite_A
  • 310
  • 2
  • 5
  • 13
  • 3
    If you pass 16 argument to a function you must be doing something wrong. Try avoiding sending more than 3 arguments. A function should do one thing and one thing only, if it's doing more than that you should refactor it. – Nir Alfasi Jan 21 '15 at 04:21
  • It's an __init__ function for a 4x4 matrix, if you have any ideas of how to refactor it, please tell. – BombSite_A Jan 21 '15 at 04:23
  • 1
    @BombSite_A Why not take in a sequence of length 16, or a sequence of four sequences of length four? – sapi Jan 21 '15 at 04:27
  • Check out my solution for a manageable and clean looking approach. – kartikg3 Jan 21 '15 at 05:47

3 Answers3

4

This is a much more managable solution than the currently accepted one. It will give you the ease of declaring your default args as tuples instead of declaring each value's names in the function signature. (Imagine doing that for a 4x4 matrix!)

update:

You can do:

def func(self, args):
    defaultargs = (1, 2, 3)
    args = tuple(map(lambda x, y: y if y is not None else x, defaultargs, args))

In this case, instead of having the default args in the function definition, you can have it inside and do an or operation on each element as shown. This way, any positions that were left blank in the args would be filled by the respective positions from the default args tuple.

This solves the caveat mentioned in the comment below.

Community
  • 1
  • 1
kartikg3
  • 2,590
  • 1
  • 16
  • 23
  • Note that this will interpret `0` values (or any value considered as false like `''` or `[]`) as not set and use the `defaultargs` value instead. – Adam Kerz Jan 21 '15 at 05:06
  • I modified the answer to solve the caveat. Thanks for pointing it out! – kartikg3 Jan 21 '15 at 05:44
  • In python 3, since map will stop iterating at the least long sequence, you should ensure that `args` is longer. One way to do that is to use `args+(None,)*len(defaultargs)` instead of `args`. – InQβ Mar 20 '18 at 04:18
3

So if I understand what you're asking, what you're interested in is the * operator. It allows you to unpack arguments out of lists/tuples, like so:

def foo(a, b, c='l', d='l', e='o'):
    return ''.join((a,b,c,d,e))

tuple1 = ('H', 'e')
tuple2 = ('H', 'o', 'w', 'd', 'y')

foo(*tuple1)
>> "Hello"
foo(*tuple2)
>> "Howdy"
Community
  • 1
  • 1
Nick Marinakis
  • 1,776
  • 2
  • 10
  • 12
0

Use

def func(self, *arg):

The arg contain the list of all parameters like ['foo', 'bar', 'foobar'] U can access by using arg[1]or arg[2]......etc

You can pass variable number of parameters like

func(('bar', 'foo')
func(('bar', 'foo','addjf')
func(('bar', 'foo','abc','xyz)

etc

Sheshananda Naidu
  • 905
  • 1
  • 9
  • 10