How to change default value of optional function parameter in Python 2.7?

狂风中的少年 提交于 2020-05-28 09:59:09

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!