问题
I need to change global variable S
at a.py
from b.py
, but it is used as a default value in a function at a.py
.
a.py
S = "string"
def f(s=S):
print(s)
print(S)
b.py
import a
def main():
a.S = "another string"
a.f()
if __name__ == "__main__":
main()
python b.py
outputs
string
another string
instead of expected
another string
another string
If I call a.f
in b.py
like this
a.f(a.S)
this works as expected, but is there any way to change default variable value?
回答1:
The short answer is: You can't.
The reason for this is that the function default arguments are created at function definition time, and the defaults are not meant to be re-defined. The variable name is bound once to a value and that is all, you can't re-bind that name to another value. First, let's look at variables in global scope:
# create a string in global scope
a = "string"
# b is "string"
b = a
a += " new" # b is still "string", a is a new object since strings are immutable
You've now just bound a new name to "string", and "string new" is a completely new value bound to a, it does not change b because str += str
returns a new str
, making a
and b
refer to different objects.
The same happens with functions:
x = "123"
# this expression is compiled here at definition time
def a(f=x):
print(f)
x = "222"
a()
# 123
The variable f
was defined with the default of "123"
at definition time. This can't be changed. Even with mutable defaults such as in this question:
x = []
def a(f=x):
print(x)
a()
[]
# mutate the reference to the default defined in the function
x.append(1)
a()
[1]
x
[1]
The default argument was already defined, and the name f
was bound to the value []
, that cannot be changed. You can mutate the value associated with f
, but you cannot bind f
to a new value as a default. To further illustrate:
x = []
def a(f=x):
f.append(1)
print(f)
a()
x
[1]
# re-defining x simply binds a new value to the name x
x = [1,2,3]
# the default is still the same value that it was when you defined the
# function, albeit, a mutable one
a()
[1, 1]
It might be better to either A) pass the global variable in as an argument to the function or B) use the global variable as global
. If you are going to change the global variable you wish to use, don't set it as a default parameter and choose a more suitable default:
# some global value
x = "some default"
# I'm choosing a default of None here
# so I can either explicitly pass something or
# check against the None singleton
def a(f=None):
f = f if f is not None else x
print(f)
a()
some default
x = "other default"
a()
other default
a('non default')
non default
来源:https://stackoverflow.com/questions/57662072/how-to-change-default-value-of-optional-function-parameter-in-python-2-7