1

Suppose I have a function foo(x,k) and suppose x is a list. I want k to default to the length of the list. Do I just write:

def foo(x, k=1):
  k = len(x)
  ..
end

I just want to run foo with one argument, namely, x.

5
  • 2
    Out of curiosity, why do you need a second parameter to your function then, rather than just using k as internally declared variable, defaulting to len(x)? Commented Feb 26, 2013 at 3:57
  • Why even have k then? Commented Feb 26, 2013 at 3:58
  • The function I am defining is recursive and relies on k as an index. Commented Feb 26, 2013 at 3:58
  • 1
    @lord12: If k is always going to be the length of the list, why do you have it as an argument? Commented Feb 26, 2013 at 3:59
  • The last sentence is quite confusing. I think you mean that you want to be able to call foo with one argument. But your last sentence says that you only ever want to call foo with one argument, which would make k a pointless parameter. Could you edit your question for clarity? Commented Feb 26, 2013 at 4:12

3 Answers 3

9

You should do:

def foo(x, k=None):
    if k is None:
        k = len(x)
    ...

Note that this could be made more compact as:

def foo(x, k=None):
    k = k or len(x)
Sign up to request clarification or add additional context in comments.

10 Comments

@thewolf, I disagree. This is the most idiomatic approach to specifying a dynamically defined default. Mutability has nothing to do with it.
@senderle: I am referring to this and this and this as examples. The assignment of k=None then testing for None has always struck me as a construct for use with optional mutables mostly and use k=kwargs.get('k',len(l)) for others since in that one line you are testing and assigning. I didn't say it was wrong at all; just surprised
Using **kwargs instead of a specific default keyword argument has a few disadvantages in this case. First, it's almost 25% slower according to a test I just did. (get is pretty slow.) Second, and more importantly, it disallows passing in k as a positional argument. Third, and most importantly, it accepts and silently ignores any keyword argument except k, whereas the above throws an error if passed an unexpected keyword argument.
@senderle: agreed, and I would add a fourth- it makes help(foo) less transparent.
@senderle: I am convinced. I tested the speed and indeed get is slower and your other arguments are correct. +1 for this and I have edited my post. I am here to learn...
|
2

Just do:

def foo(x):
    k = len(x)

You don't have to pass in k to this function. You can just use a local variable k.

In case you have to use k then you can just do:

def foo(x,k):
    k = len(x)

Although this doesn't serve any purpose.

1 Comment

I think you've misunderstood the question. Admittedly, it's not very clear. I think the point is that k should be an optional parameter. It should only take the value of len(x) if k is not supplied.
0

If your intent is to have an optional k in no particular order with k=len(l) the default, you can use an optional keyword argument like so:

def f(l,**kwargs):
    k=kwargs.get('k',len(l))    
    # if k is in kwargs, it overrides the default of len(l)..
    print 'l={}, len(l)={}, k={}'.format(l,len(l),k)

f([1,2,3])  
f([1,2,3],k=1)  

Prints:

l=[1, 2, 3], len(l)=3, k=3
l=[1, 2, 3], len(l)=3, k=1

As pointed out in the comments, this is a trade-off with other considerations of speed and parameter position in David Robinson's approach.

1 Comment

You should always avoid using lower-case 'L' as a variable name

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.