Considering the following code:
def overwrite(condition):
if condition:
return "bar"
foo = "foo"
foo = overwrite(False)
print(foo) # -> this should print "foo"
From the function perspective, we don't know the value of foo
unless it's explicitly passed as an argument to the function. I don't want to pass it because in my case this function is already very crowded and it doesn't look very pythonic this way.
Is there any way to NOT overwrite the variable and keep its original value?
CodePudding user response:
By default functions implicitly return None
if not explicitly returned in the code. Thus you get None
if condition
is False
. Try using the a ternary return statement and supply the function the value to be changed:
def overwrite(value, condition):
return "bar" if condition else value
Then to call the function:
>>> foo = overwrite(foo, False)
'foo'
>>> foo = overwrite(foo, True)
'bar'
If you wish not to call having to supply the value then you can use the global
keyword to access foo
's value from inside the function. Although I do not suggest writing code in this fashion, as now you have a generic seeming function overwrite
that only works for one value.
def overwrite(condition, value=None):
global foo
return "bar" if condition else value or foo
CodePudding user response:
You can't do it. When you assign, as in
foo = overwrite(False)
python fully resolves the right hand side to a value, and then does the assignment on the left. And that assignment could be more complicated, like
baz[10] = overwrite(False)
qux.quux = overwrite(False)
pandas_df["random column"] = overwrite(False)
The function has no idea where its return value will go so can't get its original value. And it can't stop python from doing the assignment. Your function is complicated, but this is a complication that's needed.
EDIT
As noted by others, you could let the calling code decide whether to update foo
foo = val if (val := overwrite(False) is not None) else foo
Now overwrite
doesn't care if you overwrite or not, it just returns None
when it didn't generate a settable value.
You could also create a more complicated return object that lets overwrite
return its value and whether there should be an update.
class OverwriteResult:
def __init__(self, overwrite, result):
self.overwrite = overwrite
self.result = result
def get(self, default):
return self.result if self.overwrite else default
def overwrite(condition):
if condition:
return OverwriteResult(True, "bar")
return OverwriteResult(False, None)
result = overwrite(False)
foo = result.get(foo)
I'm not sure if that's cool or overkill.