我有类似于以下代码的内容:
class thingy(object):
def __init__(creds=get_credentials()):
# does stuff
pass
def get_credentials():
# produces different values sometimes. Ie: retrieves values from a db
return db.get(some_query)
dc.connect(credentials_and_stuff)
导入时失败,而不是运行时,定义__init__()
,说'数据库没有连接'。这对我来说没有意义,因为__init__()
函数还没有运行!
答案 0 :(得分:4)
我发现了这个:http://docs.python-guide.org/en/latest/writing/gotchas/#mutable-default-arguments
事实证明,可选参数的值在执行时在定义,不时进行评估。这是一个极端的例子:
def default_value():
print("ERMAGERD DIS FUNCTION WAS RUN!")
return False
def fake_function(an_arg=default_value()):
pass
在此发现之前,我会说这段代码什么都不做;没有运行任何函数,只是一些定义。现在我知道(并且经过测试)仅此代码将打印出ERMAGERD DIS FUNCTION WAS RUN!
。
对于上述问题中的代码,这意味着两件事:
db.connect()
定义发生之前运行class thingy(object)
。get_credentials()
只会运行一次,并且说db查询永远不会重新运行(过时的凭据!)因此,为了使实际上做它想要做的事情(在没有提供时查询数据库中的凭据),你必须做类似于这样的事情:
class thingy(object):
def __init__(creds=None):
if creds is None:
creds = get_credentials()
# does stuff
pass
这种方式get_credentials()
在运行时运行,而不是在定义时运行。这两者都允许db.connect()
在其他地方完成(只要它在实例化thingy
的实例之前),和修复了陈旧的凭据问题。