This question already has answers here:
When are function arguments evaluated?
(4 answers)
Closed 1 year ago.
I always assumed that the default value in the myDict.get('key', default_value) expression was never called if the key exists in the dictionary. However, I have recently found out it somehow is. For example, consider the code
def doSomething():
print('Done')
return 'Another value'
myDict = {'key': 'value'}
print(myDict.get('key', doSomething()))
One would expect that since key exists in myDict, then the only thing myDict.get('key', doSomething()) would do is to return value and hence, the function doSomething would never be called. This is not the case however, and running this code in python currently outputs:
Done
value
My question is: why is this the case? Why isn't the default_value ignored completely when the key exists?
And what can be done to change this, that is, to not call the default_value when the key exists?
That's because the get method of a dictionary does not accept a callback as Java's computeIfAbsent, but a value. If you want it to not be called, you can do it using the ternary expression:
print(doSomething() if myDict.get('key') is None else myDict.get('key'))
The way you've written it, doSomething() is executed before myDict.get() is called, and its return value (which is implicitly None, because there's no return statement) is passed in as the default.
print(myDict.get('key', doSomething()))
# evaluates to
print(myDict.get('key', None))
# evaluates to
print('value')
As a rule of thumb, passing an expression as a function argument will always have the expression evaluated first, before its result is passed as that argument.
get() does not have the ability to run a separate function upon a nonexistent key. If you pass a lambda in as the default, you'd get the same lambda back out as the default, uncalled.
Related
I wanted to have the option to pass my arguments to a function in a concise manner. So instead of passing all arguments directly, I include them as parameters function definiton and pass all such arguments as Common_Args. Then I do the following
for key, value in Common_args.items():
if key in locals():
globals()[key] = value
Here is the problem. Even though the control goes inside the if condition(checked with debugger), the parameter's value do not change, but it should, right?
Guides have confirmed that this should work, and if I run single statements in my debugger, the value of the variable does change.
My function definition in more detail is
def plotLFPData1Channel(plotHandles=None, channelString="", stimulus_list=None, folderName=None, analysisType=None,
timeVals=None, plotColor=None, blRange=None, stRange=None, referenceChannelString=None,
badTrialNameStr=None, useCommonBadTrialsFlag=None ,*,Common_args=None):
# first we have to unpack common args
if Common_args is not None:
for key, value in Common_args.items():
if key in locals():
globals()[key] = value
and I call the function like so
result=plotLFPData1Channel(plotHandles=ax.flatten(), channelString=analogChannelString, stimulus_list=stimValsToUse,analysisType=analysisType,Common_args=commonArgs)
with commonArgs={"folderName":folderName , "timeVals":timeVals, "plotColor":plotColor, "blRange":blRange, "stRange":stRange, "referenceChannelString":referenceChannelString, "badTrialNameStr":badTrialNameStr, "useCommonBadTrialsFlag":useCommonBadTrialsFlag}
This question already has answers here:
How to force the default parameter in python
(4 answers)
Call function without optional arguments if they are None
(10 answers)
Closed 1 year ago.
Is there a way to call a function with an argument but have the argument in a way that the default value of the function is used instead? Like
def f(val="hello"):
print(val)
def g(a=Undefined): #replace Undefined with something else
f(a)
>>> g()
hello
The reason is, the called function is not under my control and I want to inherit its default value. Of course I could
def h(a=None):
f(a) if a else f()
or even
def k(a=None):
j = lambda : f(a) if a else f()
j()
since I have to call that function a few times and also pass other parameters. But all that would be much easier if I could just tell the function I want to use its default value.
I could also simply copy paste the default value to my function, but don't want to update my function if the other one changes.
So I have a python function that is explicitly returning a value, however my unittest receives None.
Here the function is seen returning a str value:
But my unittest receives None. see validation_result
Any ideas on what is causing the return value to default to None? I am explicitly returning a value??
The code you've highlighted just tells you what the value of the constant is - NOT that it's the value being returned from the method.
Your code returns before the return VALIDATION_SUCCESS statement is invoked - look for an empty return statement, or an explicit return None (or if VALIDATION_FAILED or other constants is set to None as well).
You can use the step through / step over functionality in your debugger to find out where it returns (since you've already set a breakpoint). Set the breakpoint at the start of the method / function you're calling into, and then step through the code to find out where your assumption is wrong.
I figured out my problem.
My execute function had a #decorator method that was missing a return statement, so the decorator had the returned value I was expecting, but then not returning the wrapped function containing it, and thus it was defaulting to None.
This question already has answers here:
"Least Astonishment" and the Mutable Default Argument
(33 answers)
Closed 6 years ago.
I am confused by the following example:
def append(elem, to=None):
if to is None:
to = []
to.append(elem)
return to
append(5)
# Out: [5]
append(3) # A new list is created
# Out: [3]
The point here is supposed to be that you are resetting "to" to an empty list at the beginning of every function call to avoid the following:
append(5)
# Out: [5]
append(3) # A new list is created
# Out: [5, 3]
But how can you check that "to" is None to set it to []? It seems to me that you are either pulling in the "to" defined in the definition, or you are pulling in the "to" modified by the last call. How does this work?
When you define a function with a default argument, the function uses that default values for that argument if it is not supplied. So in the case of append(5), to is not specified, so the function assumes the value of to to be None - it's effectively the same as calling append(5, None).
So now, the function checks if to is None, which it is, so to gets reassigned to an empty list. 5 gets appended to the list, and the list is returned.
When you make the second call append(3), it is again as if you called append(3, None). Again, the if to is None evaluates to True, and to is reassigned to an empty list. Then, 3 is appended to that empty list, and the list is returned.
Since the default argument (in this case None) is immutable, the operations on to do not persist the end of the function call. The function has its own chunk of memory which gets cleared when the function returns.
However, if the default argument was mutable (like for instance []), that value is created when the function is defined (i.e. when python sees def func(arg1, arg2=[]), it creates an empty list in memory and uses that list every time this function is called). Thus, any changes made to that list will persist the end of the function, since that mutable default argument was created when the function was defined (before the function was ever called).
I'll be quoting Common Gotchas — The Hitchhiker's Guide to Python here:
For example like:
def append_to(element, to=[]):
to.append(element)
return to
A new list is created once when the function is defined, and the same
list is used in each successive call.
Python’s default arguments are evaluated once when the function is
defined, not each time the function is called (like it is in say,
Ruby). This means that if you use a mutable default argument and
mutate it, you will and have mutated that object for all future calls
to the function as well.
Also if you don't like to use none ant consider it an antipattern, you can use more fancier kind of this:
def append_to(element, to=list):
if callable(to):
to = to()
to.append(element)
return to
I don't know if it's better though
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is there any way to know if the value of an argument is the default vs. user-specified?
python - returning a default value
It is standard practice in Python to use None as the default parameter value.
However, this idiomatic usage doesn't work well if client code may use None as a legal argument value. In this case, the function cannot tell whether the client code omitted the argument, or whether it explicitly passed None. This is not good, unless (by luck) the function's behavior should be the same in both cases.
What is a good solution?
_NOT_SET = object()
def some_function(some_arg=_NOT_SET):
if some_arg is _NOT_SET:
# ...
Any class instance has a unique identity that is can tell apart.