简体   繁体   English

如何更改可选函数参数的默认值

[英]How to change default value of optional function parameter

I need to change the global variable S at a.py from b.py , but it is used as a default value in a function at a.py .我需要从b.py更改a.py的全局变量S ,但它用作a.py函数中的默认值。

a.py一个.py

S = "string"


def f(s=S):
    print(s)
    print(S)

b.py b.py

import a


def main():
    a.S = "another string"
    a.f()


if __name__ == "__main__":
    main()

python b.py outputs python b.py输出

string
another string

instead of expected而不是预期

another string
another string

If I call af in b.py like this如果我像这样在b.py调用af

a.f(a.S)

this works as expected, but is there any way to change default variable value?这按预期工作,但是有什么方法可以更改默认变量值吗?

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.您现在刚刚将一个新名称绑定到“string”,而“string new”是一个绑定到 a 的全新值,它不会改变 b 因为str += str返回一个新的str ,使ab指代不同对象。

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.变量f在定义时使用默认值"123"定义。 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.默认参数已经定义,名称f绑定到值[] ,不能更改。 You can mutate the value associated with f , but you cannot bind f to a new value as a default.您可以改变与f关联的值,但不能将f绑定到新值作为默认值。 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 . A) 将全局变量作为参数传递给函数或 B) 使用全局变量作为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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM