As you've discovered global variables don't work like that - nor should they. Here are some things you can do, but shouldn't.
myfunctions.py
ref = 30
def f(x):
print x + ref
our_caller.py
import myfunctions
myfunctions.f(10) # prints 40
myfunctions.ref = 50
myfunctions.f(10) # prints 60
But then what about some_other_caller.py ?
import myfunctions
myfunctions.f(20) # prints 50? prints 70?
It depends on when you messed around with the global variable in the myfunctions module.
Additionally, as a thought experiment, imagine the code you posted above did work as you expected (it would in some languages). What happens in the case where some_other_caller imports our_caller which imports myfunctions. Which ref is used then? It could be more complex, some_other_caller could call a function in our_caller which in turn calls myfunctions.f - so we use the ref from our_caller? So the behaviour is potentially different if some_other_caller called myfunctions directly?
That's not a world anyone wants to live in.
The better way of doing it is more like:
myfunctions.py
def f(x, ref=30):
print x + ref
our_caller.py
import myfunctions
myfunctions.f(10) # prints 40
myfunctions.f(10, ref=50) # prints 60
Then people can see what's going on - there's no weird state changing. Global state really is best avoided. You'll hear that again and again. Ignore that advice at your own peril (and that of any poor soul that has to support your code later).
EDIT: Additional to your comment above about your use case it's not uncommon to see a patterns like the following.
REF = 30
ref_count = 0
def f(x, ref=REF, other_thing=None):
if not other_thing:
other_thing = ref_count
print x + ref + other_thing
def add_ref(current_count=None):
global ref_count
if current_count is not None:
ref_count = current_count
ref_count += 1
You can keep the global variables (REF is more like a global constant). When you call f externally you can choose to supply values for them or allow them to be the defaults. Also, you can call add_ref, supplying it with a new value to use for the global copy in the module.
Again, same rules apply - you've added global state to your module that can be effected by external modules. You need to be very careful about who's changing it and a better architecture would attempt to avoid this situation in the first instance.