467,114 Members | 1,410 Online

# What value should be passed to make a function use the default argument value?

 Suppose I have this function: def f(var=1): return var*2 What value do I have to pass to f() if I want it to evaluate var to 1? I know that f() will return 2, but what if I absolutely want to pass a value to f()? "None" doesn't seem to work.. Thanks in advance. Oct 3 '06 #1
• viewed: 2732
Share:
50 Replies
 LaundroMat
 LaundroMat wrote: Suppose I have this function: def f(var=1): return var*2 What value do I have to pass to f() if I want it to evaluate var to 1? I know that f() will return 2, but what if I absolutely want to pass a value to f()? f(1) "None" doesn't seem to work.. None is an object. Oct 3 '06 #3
 def f(var=1): return var*2 What value do I have to pass to f() if I want it to evaluate var to 1? I know that f() will return 2, but what if I absolutely want to pass a value to f()? "None" doesn't seem to work.. >>def f(var=1): .... return var*2 .... >>f() 2 >>f(0.5) 1.0 >>f(123) 246 >>f('hello') 'hellohello' I'm not sure I follow your problem...what's stopping you from passing a value? -tkc Oct 3 '06 #4
 LaundroMat wrote: Suppose I have this function: def f(var=1): return var*2 What value do I have to pass to f() if I want it to evaluate var to 1? I know that f() will return 2, but what if I absolutely want to pass a value to f()? "None" doesn't seem to work.. Thanks in advance. The answer is don't pass any value. print f() will print 2 -Larry Bates Oct 3 '06 #5
 On Tue, 03 Oct 2006 13:16:57 -0700, "LaundroMat" >def f(v=1): .... return v*2 .... >>f() 2 >>f(1) 2 >>f(*[1]) 2 >>f(*[]) 2 >>> *[list] is the reverse of def f(*args) -- Thomas Jollans alias free-zombie Oct 3 '06 #6
 LaundroMat wrote: Suppose I have this function: def f(var=1): return var*2 What value do I have to pass to f() if I want it to evaluate var to 1? I know that f() will return 2, but what if I absolutely want to pass a value to f()? "None" doesn't seem to work.. What about this? >>def f(var=None): .... if var == None: .... var = 1 .... return 2*var .... >>f() 2 >>f(3) 6 >>a=4f(a) 8 >>b=Nonef(b) 2 >>> --Stan Graves Oct 3 '06 #7
 LaundroMat a écrit : Suppose I have this function: def f(var=1): return var*2 What value do I have to pass to f() if I want it to evaluate var to 1? I know that f() will return 2, but what if I absolutely want to pass a value to f()? "None" doesn't seem to work.. Have you tried f(1) ? Oct 3 '06 #8
 LaundroMat wrote: Suppose I have this function: def f(var=1): return var*2 What value do I have to pass to f() if I want it to evaluate var to 1? I know that f() will return 2, but what if I absolutely want to pass a value to f()? "None" doesn't seem to work.. If you *absolutely* want to pass a value and you don't know the default value (otherwise you could just pass it): >>import inspectv = inspect.getargspec(f)[3][0] # first default valuef(v) 2 Oct 3 '06 #9
 On 2006-10-03, LaundroMat
 Rob De Almeida wrote: LaundroMat wrote: Suppose I have this function: def f(var=1): return var*2 What value do I have to pass to f() if I want it to evaluate var to 1? I know that f() will return 2, but what if I absolutely want to pass a value to f()? "None" doesn't seem to work.. If you *absolutely* want to pass a value and you don't know the default value (otherwise you could just pass it): >import inspectv = inspect.getargspec(f)[3][0] # first default valuef(v) 2 I have in fact a bunch of functions that all pass similar information to one main function. That function takes (amongst others) a template variable. If it's not being passed, it is set to a default value by the function called upon. For the moment, whenever a function calls the main function, I check whether the calling function has the template variable set: >>if template: return mainFunction(var, template)else: return mainFunction(var) Now, I thought this isn't the cleanest way to do things; so I was looking for ways to initialize the template variable, so that I could always return mainFunction(var, template). mainFunction() would then assign the default value to template. >From your answers, this seems to be impossible. The minute my variable is initialised, there's no way I can have mainFunction() assign a value without explicitly asking it to do so. I guess the best way would then be to change mainFunction from: >>def mainFunction(var, template='base'): to >>def mainFunction(var, template):if len(template)=0: template = 'base' and have the calling functions call mainFunction (var, template) and initialise template to ''. I still have that nagging feeling nicer code could be written to solve this, but I won't try to lose any sleep over it. Thanks for all the replies. Oct 4 '06 #11
 "LaundroMat"
 On 2006-10-04, Paul Rubin def f(var=1):return var*2What value do I have to pass to f() if I want it to evaluate var to 1?I know that f() will return 2, but what if I absolutely want to pass avalue to f()? "None" doesn't seem to work.. I don't understand your question. You can call f(var=1) just fine. The problem is like the following. def f(var=1): return var*2 def g(): arg = None try: arg = Try_Processing() / 3 + 1 except Nothing_To_Process: pass if arg is None: return f() else: return f(arg) Now in this case you could start by assigning arg the value 1 and eliminate the if test. However that only works if you know the default value for the argument. What he seems to be asking for is if there is an object, (let as call it Default), that would make code like: def f(var=1): Equivallent to: def f(var=Default) if var is Default) var = 1 So that we could write the following without the need of the f's default value. def g(): arg = Default try: arg = Try_Processing() / 3 + 1 except Nothing_To_Process: pass f(arg) -- Antoon Pardon Oct 4 '06 #13
 Antoon Pardon wrote: The problem is like the following. def f(var=1): return var*2 def g(): arg = None try: arg = Try_Processing() / 3 + 1 except Nothing_To_Process: pass if arg is None: return f() else: return f(arg) Now in this case you could start by assigning arg the value 1 and eliminate the if test. However that only works if you know the default value for the argument. What he seems to be asking for is if there is an object, (let as call it Default), that would make code like: def f(var=1): Equivallent to: def f(var=Default) if var is Default) var = 1 So that we could write the following without the need of the f's default value. def g(): arg = Default try: arg = Try_Processing() / 3 + 1 except Nothing_To_Process: pass f(arg) -- Antoon Pardon Exactly. Thanks for helping out. Oct 4 '06 #14
 Antoon Pardon
 LaundroMat if template: return mainFunction(var, template)else: return mainFunction(var) Now, I thought this isn't the cleanest way to do things; so I was looking for ways to initialize the template variable, so that I could always return mainFunction(var, template). mainFunction() would then assign the default value to template. From your answers, this seems to be impossible. The minute my variable is initialised, there's no way I can have mainFunction() assign a value without explicitly asking it to do so. I guess the best way would then be to change mainFunction from: >def mainFunction(var, template='base'): to >def mainFunction(var, template):if len(template)=0: template = 'base' and have the calling functions call mainFunction (var, template) and initialise template to ''. None is the traditional value to use for value not present, then you'd get this for the function def mainFunction(var, template=None): if template is None: template = 'base' And this for the calling bit if not_set_properly(template): template = None return mainFunction(var, template) -- Nick Craig-Wood
 Antoon Pardon
 On 2006-10-04, Nick Craig-Wood One possible way to do what I think you want is to code as follows: class Default (object): pass I'd have written Default = object() > def f(var=Default): if var is Default: var = 1 return var * 2 But yes, defining a sentinel like this is a good idea. The problem is that a lot of built in and library functions are not written this way. So when f is one of those, you are stuck. -- Antoon Pardon Oct 4 '06 #18
 On 2006-10-04, Paul Rubin Now in this case you could start by assigning arg the value 1 andeliminate the if test. However that only works if you know thedefault value for the argument. What he seems to be asking foris if there is an object, (let as call it Default), that wouldmake code like: def f(var=1):Equivallent to: def f(var=Default) if var is Default) var = 1 Oh, I see. Yes, the OP should just use a distinct default value instead of 1. I usually do this with sentinel = object() def f(var=sentinel): if var is sentinel: # f was called without an arg But that can only work if you are the author of f. Take the following code: def myrepeat(obj, times = xxx): return itertools.repeat(obj, times) What value do I have to substitue for xxx, so that myrepeat will have the exact same function as itertools.repeat? -- Antoon Pardon Oct 4 '06 #19
 Antoon Pardon wrote: On 2006-10-04, Paul Rubin Antoon Pardon >Now in this case you could start by assigning arg the value 1 andeliminate the if test. However that only works if you know thedefault value for the argument. What he seems to be asking foris if there is an object, (let as call it Default), that wouldmake code like: def f(var=1):Equivallent to: def f(var=Default) if var is Default) var = 1 Oh, I see. Yes, the OP should just use a distinct default valueinstead of 1. I usually do this with sentinel = object() def f(var=sentinel): if var is sentinel: # f was called without an arg But that can only work if you are the author of f. Take the following code: def myrepeat(obj, times = xxx): return itertools.repeat(obj, times) What value do I have to substitue for xxx, so that myrepeat will have the exact same function as itertools.repeat? There's no possible value. You'll have to write this like def myrepeat(obj, times=None): if times is None: return itertools.repeat(obj) else: return itertools.repeat(obj, times) Many functions implemented in C have this behavior. For all functions written in Python, you can look up the default value in the source. Georg Oct 4 '06 #20
 Georg Brandl wrote: >But that can only work if you are the author of f. Take thefollowing code: def myrepeat(obj, times = xxx): return itertools.repeat(obj, times)What value do I have to substitue for xxx, so that myrepeatwill have the exact same function as itertools.repeat? There's no possible value. You'll have to write this like def myrepeat(obj, times=None): if times is None: return itertools.repeat(obj) else: return itertools.repeat(obj, times) or: def myrepeat(*args): return itertools.repeat(*args) Oct 4 '06 #21
 On 2006-10-04, Georg Brandl On 2006-10-04, Paul Rubin >Antoon Pardon
 On 2006-10-04, Fredrik Lundh >But that can only work if you are the author of f. Take thefollowing code: def myrepeat(obj, times = xxx): return itertools.repeat(obj, times)What value do I have to substitue for xxx, so that myrepeatwill have the exact same function as itertools.repeat? There's no possible value. You'll have to write this likedef myrepeat(obj, times=None): if times is None: return itertools.repeat(obj) else: return itertools.repeat(obj, times) or: def myrepeat(*args): return itertools.repeat(*args) Yes that works but I have the impression that this solution becomes complicated very fast once you want to do extra processing in the function body. Take the following def myrepeat(obj, times = xxx)" newobj = Process(obj) return itertools.repeat(obj, times) I think it would become something like: def myrepeat(*args): obj = args[0] tail = args[1:] newobj = Process(obj) newargs = (newobj,) + tail return itertools.repeat(*newargs) Oct 4 '06 #23
 Antoon Pardon
 Antoon Pardon
 On 2006-10-03, LaundroMat
 On 2006-10-04, Antoon Pardon Suppose I have this function:def f(var=1):return var*2What value do I have to pass to f() if I want it to evaluate var to 1?I know that f() will return 2, but what if I absolutely want to pass avalue to f()? "None" doesn't seem to work..Thanks in advance. I think the only general solution for your problem would be to define a defaulter function. Something like the following: Default = object() def defaulter(f, *args): while args: if args[-1] is Default: args = args[:-1] else: break return f(*args) The call: defaulter(f, arg1, arg2, Default, ..., Default) would then be equivallent to: f(arg1, arg2) Or in your case you would call: defaulter(f, Default) A little update, with the functools in python 2.5 you could turn the above into a decorator. Something like the following (not tested): def defaulting(f): return functools.partial(defaulter, f) You could then simply write: @defaulting def f(var=1): return var * 2 And for built in or library functions something like: from itertools import repeat repeat = defaulting(repeat) -- Antoon Pardon Oct 4 '06 #27
 Paul Rubin wrote: Antoon Pardon repeat(object[, times]) Make an iterator that returns object over and over again. Runs indefinitely unless the times argument is specified. ...My first impression from this, is that it is possible to callthis as follows: repeat(None, times = 5)But that doesn't work either. The code and/or doc is wrong, you have to use a positional arg and not a named one. repeat(None, 5) does the right thing. This is an issue in most Python documentation: you're not told if the described function is implemented in C, and if it is keyword arg-enabled. The arguments must be given names though, to be able to document them. Georg Oct 4 '06 #28
 Georg Brandl wrote: This is an issue in most Python documentation: you're not told if the described function is implemented in C, and if it is keyword arg-enabled. The arguments must be given names though, to be able to document them. the general rule is that if the documentation doesn't explicitly say that something is a keyword argument, it isn't, and shouldn't be treated as such. Oct 4 '06 #29
 On 2006-10-04, Fredrik Lundh This is an issue in most Python documentation: you're not toldif the described function is implemented in C, and if it iskeyword arg-enabled. The arguments must be given names though,to be able to document them. the general rule is that if the documentation doesn't explicitly say that something is a keyword argument, it isn't, and shouldn't be treated as such. The first module I looked in to check this, it wasn't true. In the Queue Module is isn't explicitly written that maxsize is a keyword argument yet Queue.Queue(maxsize=9) works just fine. I then took a look in the Threading module and found that the semaphore documentation didn't mention anything about keyword arguments but again they worked fine. It wouldn't surprise me if this was true for the complete threading documentation. -- Antoon Pardon Oct 5 '06 #30
 Antoon Pardon wrote: The first module I looked in to check this, it wasn't true. In the Queue Module is isn't explicitly written that maxsize is a keyword argument yet Queue.Queue(maxsize=9) works just fine. it's not a matter whether it works fine in any given version of Python, it's a matter of whether it's *guaranteed* to work. Oct 5 '06 #31
 Fredrik Lundh wrote: Antoon Pardon wrote: >>The first module I looked in to check this, it wasn't true. In the QueueModule is isn't explicitly written that maxsize is a keyword argument yetQueue.Queue(maxsize=9) works just fine. it's not a matter whether it works fine in any given version of Python, it's a matter of whether it's *guaranteed* to work. There are some sloppy places in the docs, though, perhaps where a function has started out with positionals only and keyword arguments have been added later, or it's just plain wrong. I remember an incident a month or so ago when someone had called cgi.parse with a second positional to retain blank values - the docs for 2.4.2 say: parse( fp[, keep_blank_values[, strict_parsing]]) but the function signature in the code is def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0) IIRC he reported this as a doc bug, though probably just too late to make it into the initial 2.5 release. You can imagine his CGI scripts didn't run too well with an integer as the environment ;-) Someone with a tendency to salt every snail (that's dotting all the i's and crossing all the t's for you English-speakers out there :-) could probably do the community a service by reviewing the documented signatures and report such discrepancies. regards Steve -- Steve Holden +44 150 684 7255 +1 800 494 3119 Holden Web LLC/Ltd http://www.holdenweb.com Skype: holdenweb http://holdenweb.blogspot.com Recent Ramblings http://del.icio.us/steve.holden Oct 5 '06 #32
 At Thursday 5/10/2006 11:41, Antoon Pardon wrote: the general rule is that if the documentation doesn't explicitly say that something is a keyword argument, it isn't, and shouldn't be treated as such. The first module I looked in to check this, it wasn't true. In the QueueModule is isn't explicitly written that maxsize is a keyword argument yetQueue.Queue(maxsize=9) works just fine. This is true for most python code, unless the arguments are get as *args. But it's not the same for the C code, where the argument parsing must be done explicitely. Gabriel Genellina Softlab SRL __________________________________________________ Preguntá. Respondé. Descubrí. Todo lo que querías saber, y lo que ni imaginabas, está en Yahoo! Respuestas (Beta). ¡Probalo ya! http://www.yahoo.com.ar/respuestas Oct 5 '06 #33
 Gabriel Genellina wrote: the general rule is that if the documentation doesn't explicitly say that something is a keyword argument, it isn't, and shouldn't be treated as such. The first module I looked in to check this, it wasn't true. In the QueueModule is isn't explicitly written that maxsize is a keyword argument yetQueue.Queue(maxsize=9) works just fine. This is true for most python code, unless the arguments are get as *args. you guys need to look up the words "should" and "not" in a dictionary. Oct 5 '06 #34
 Fredrik Lundh
 Ben Finney wrote: Perhaps you meant something other than "if the documentation doesn't explicitly say that something is a keyword argument, it isn't", then. I'm sure it's perfectly possibly to use your foot as a door stop, but does that really mean that it is one? Oct 6 '06 #36
 On 2006-10-04, Fredrik Lundh This is an issue in most Python documentation: you're not toldif the described function is implemented in C, and if it iskeyword arg-enabled. The arguments must be given names though,to be able to document them. the general rule is that if the documentation doesn't explicitly say that something is a keyword argument, it isn't, and shouldn't be treated as such. Is this general rules documeted somewhere? My impression is that readers of the documentation will treat arguments as keyword arguments unless this is explicitly contradicted. The reason for this is that when they learn about writing functions, parameters can be used as keuword arguments by default. So I don't think you can fault the readers for treating the documentation as if it is talking about python functions. -- Antoon Pardon Oct 6 '06 #37
 Antoon Pardon wrote: Is this general rules documeted somewhere? My impression is that readers of the documentation will treat arguments as keyword arguments unless this is explicitly contradicted. Sorry, I missed that this was comp.lang.python.alternate.reality. My mistake. Oct 6 '06 #38
 On 2006-10-06, Fredrik Lundh Is this general rules documeted somewhere? My impression is that readersof the documentation will treat arguments as keyword arguments unlessthis is explicitly contradicted. Sorry, I missed that this was comp.lang.python.alternate.reality. My mistake. A personal attack won't make my argument go away. It also doesn't answer my question. -- Antoon Pardon Oct 6 '06 #39
 On 6 Oct 2006 09:21:11 GMT, Antoon Pardon
 hanumizzle wrote: Not sure exactly what is going on / being argued about in this thread I'm describing best practices based on long experience of using and developing and teaching and writing about Python stuff. Others have other priorities, it seems. This doesn't say anything positive or negative about the practice in question The tutorial tends to describe mechanisms, not best practices, and it also assumes prior programming experience. After all, basic stuff like "minimize coupling" and "don't depend on implementation artifacts" apply to all software engineering, not just Python. Oct 6 '06 #41
 On 2006-10-06, hanumizzle On 2006-10-06, Fredrik Lundh
 On 2006-10-06, Fredrik Lundh Not sure exactly what is going on / being argued about in this thread I'm describing best practices based on long experience of using and developing and teaching and writing about Python stuff. Others have other priorities, it seems. I just think you shouldn't assume the readers of the documentation are aware of best practices. -- Antoon Pardon Oct 6 '06 #43
 Antoon Pardon wrote: IMO this is a very natural thought process for a python programmer. So a python programmer seeing the first will tend to expect that last call to work. on the other hand, if a Python programmer *writes* some code instead; say, a trivial function like: def calculate(a, b): # approximate; gonna have to fix this later return a + b * 1.2 chances are that he did *not* intend this to be called as calculate(a=1, b=2) or, for that matter, calculate(b=2, a=1) or calculate(1, b=2) just because the Python calling machinery currently happens to allow that. And chances are that he did *not* expect to be stuck with those argument names for the foreseeable future, just because someone else decided to interpret things in the most literal way they possibly could. Python 2.X doesn't provide convenient support for distinguishing between accidental and intentional argument names when you implement a function; that's a wart, not a feature, and it may be addressed in 3.X. Oct 6 '06 #44
 On Fri, 06 Oct 2006 12:42:08 +0200, Fredrik Lundh wrote: Antoon Pardon wrote: >IMO this is a very natural thought process for a python programmer.So a python programmer seeing the first will tend to expect thatlast call to work. on the other hand, if a Python programmer *writes* some code instead; say, a trivial function like: def calculate(a, b): # approximate; gonna have to fix this later return a + b * 1.2 chances are that he did *not* intend this to be called as calculate(a=1, b=2) Developers enable lots of things that they didn't intend. For example, that function works perfectly well with complex numbers, regardless of whether or not the developer who wrote it even knows that complex numbers exist. We've recently had rather vigorous argument on this list about an alleged bug in cgi.escape, and the consensus was that it wasn't a bug, but *even if it were* it couldn't be changed without making a backwards-incompatible change, and therefore it wouldn't be changed. For the developer to change the names of a and b in the above published code would be a backwards-incompatible change. Under the currently existing Python (rather than some future, hypothetical Python, or some Python in an alternative reality) all Python arguments are keyword arguments, whether the developer intends it or not. (Functions written in C are different.) At the very least, since names a and b are now part of his code's published interface, he is responsible for documenting that they are subject to change. The argument that we should assume that argument names are subject to change unless told otherwise gets it backwards -- argument names are part of the published interface to the code, just like the function name, and therefore should NOT change without warning, if at all. Now, since so many programmers seem to ignore best-practices, common practices and even common sense, perhaps Fredrik's heuristic "don't assume keyword args are keyword args unless explicitly told" might be good, defensive programming -- a little like "just because the published interface says the function returns an integer, don't assume it returns an integer without checking" might be good, defensive practice too. or, for that matter, calculate(b=2, a=1) or calculate(1, b=2) just because the Python calling machinery currently happens to allow that. And chances are that he did *not* expect to be stuck with those argument names for the foreseeable future, just because someone else decided to interpret things in the most literal way they possibly could. There is a convention for marking names as "touch at your own risk". That convention isn't "everything is touch at your own risk unless told otherwise". The convention is to use names with a leading underscore. -- Steve. Oct 7 '06 #46
 On 6 Oct 2006 10:57:01 GMT, Antoon Pardon
 Antoon Pardon wrote: Well maybe he didn't intend that, but how is the reader of the documentation to know that? The reader can only go by how things are documented. If those are not entirely consistent with the intend of the programmer, that is not the readers fault. I don't think I ever assumed that it was right to call functions with keyword arguments if they weren't defined with keyword parameters, but when I read 4.7.2 of the tutorial, I can see that it's stated through an example that this is a correct thing to do. I suppose the tutorial (and maybe the language reference) should be corrected if this isn't supposed to be guaranteed behavior. It seems like a bad idea to have different calling semantics depending on whether a callable is implemented in C or Python. Even if non-keyword parameters in Python implemented callables, *can* be called with keyword arguments, it seems like a bad idea to encourage that use. Perhaps it would be a good idea to deprecate that possibility and remove it in Python 3.0? I think it's better to force some calls into using f(*a, **kw) instead of f(**kw) if it decreases the risk that reimplementing functions in C in an API will break client code. Sure, it's simple to make a Python wrapper, but if you're after raw speed, you might not want to do that. The main downside to removing the possibility of calling non keyword parameters with keyword arguments might be that using keyword arguments could fill a documentation purpose in the code, e.g. x=get(host=arg[0], port=arg[1], path=arg[2]) would be clearer than x=get(arg[0], arg[1], arg[2]). Of course, host, port, path = arg; x=get(host, port, path) is even better (if s/;/\n) but in some cases, it's better to be able to inline things. Oct 12 '06 #48
 On 2006-10-12, Magnus Lycka Well maybe he didn't intend that, but how is the reader of thedocumentation to know that? The reader can only go by howthings are documented. If those are not entirely consistentwith the intend of the programmer, that is not the readersfault. I don't think I ever assumed that it was right to call functions with keyword arguments if they weren't defined with keyword parameters, I'm not sure I follow here. AFAICS, you can't define keyword parameters. You can give default values to parameters but this is orthogonal to calling a function with keywords. If we somehow want to seperate parameters in those that can be used with a keyword and those that don't it has to be something different than providing a default value to that parameter. -- Antoon Pardon Oct 13 '06 #49
 Antoon Pardon wrote: On 2006-10-12, Magnus Lycka >Antoon Pardon wrote: >>>Well maybe he didn't intend that, but how is the reader of thedocumentation to know that? The reader can only go by howthings are documented. If those are not entirely consistentwith the intend of the programmer, that is not the readersfault. I don't think I ever assumed that it was right to call functionswith keyword arguments if they weren't defined with keywordparameters, I'm not sure I follow here. AFAICS, you can't define keyword parameters. You can give default values to parameters but this is orthogonal to calling a function with keywords. Yup, that's a point that the documentation doesn't make stringly enough. If we somehow want to seperate parameters in those that can be used with a keyword and those that don't it has to be something different than providing a default value to that parameter. Indeed. regards Steve -- Steve Holden +44 150 684 7255 +1 800 494 3119 Holden Web LLC/Ltd http://www.holdenweb.com Skype: holdenweb http://holdenweb.blogspot.com Recent Ramblings http://del.icio.us/steve.holden Oct 13 '06 #50
50 Replies

### This discussion thread is closed

Replies have been disabled for this discussion.