Home > Blockchain >  Overwrite variables if condition is met, else keep existing values
Overwrite variables if condition is met, else keep existing values

Time:11-18

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.

  • Related