__init__函数似乎在定义上执行,而不是实例化

时间:2014-09-05 20:10:26

标签: python

我有类似于以下代码的内容:

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__()函数还没有运行!

1 个答案:

答案 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!

对于上述问题中的代码,这意味着两件事:

  1. 为了不崩溃,必须在db.connect()定义发生之前运行class thingy(object)
  2. get_credentials()只会运行一次,并且说db查询永远不会重新运行(过时的凭据!)
  3. 因此,为了使实际上做它想要做的事情(在没有提供时查询数据库中的凭据),你必须做类似于这样的事情:

    class thingy(object):
        def __init__(creds=None):
            if creds is None:
                creds = get_credentials()
            # does stuff
            pass
    

    这种方式get_credentials()在运行时运行,而不是在定义时运行。这两者都允许db.connect()在其他地方完成(只要它在实例化thingy的实例之前),修复了陈旧的凭据问题。