【问题标题】:Python - passing a method with parameters as parameter to another method - assigning defaultPython - 将带有参数的方法作为参数传递给另一个方法 - 分配默认值
【发布时间】:2014-07-01 12:37:10
【问题描述】:

表达式logic=_changelog_txt

def writeChangelog(repo, milestone, overwrite=False, extension=u'.txt',
                   logic=_changelog_txt): # HERE
    """Write 'Changelog - <milestone>.txt'"""
    outFile = _outFile(dir_=CHANGELOGS_DIR,
                       name=u'Changelog - ' + milestone.title + extension)
    if os.path.isfile(outFile) and not overwrite: return outFile
    issues = getClosedIssues(repo, milestone, skip_labels=SKIP_LABELS)
    return logic(issues, milestone, outFile)

def writeChangelogBBcode(repo, milestone, overwrite=False):
    """Write 'Changelog - <milestone>.bbcode.txt'"""
    return writeChangelog(repo, milestone, overwrite, extension=u'.bbcode.txt',
                          logic=_changelog_bbcode) # no errors here

def _changelog_txt(issues, milestone, outFile):
    with open(outFile, 'w') as out:
        out.write(h2(_title(milestone)))
        out.write('\n'.join(ul(issues, closedIssue)))
        out.write('\n')
    return outFile

给我Unresolved reference \_changelog\_txt。做我想做的最pythonic的方式是什么?另见:What is the best way to pass a method (with parameters) to another method in python

【问题讨论】:

  • 你需要在writeChangelog方法之前定义_changelog_txt方法,因为默认参数是在定义函数时实例化的,所以此时_changelog_txt不存在。
  • 跟 PyCharm 有关系吗?否则你应该得到一个NameError: name '_changelog_txt' is not defined
  • @Germano:是的,我使用 PyCharm :)
  • @Germano:不需要 - 我只是重新安排了方法 - :D

标签: python python-2.7


【解决方案1】:

这是一个顺序问题。因为在定义函数`writeChangelog时_changelog_txt还没有定义,所以会报错。

这行得通:

def b(s):
    print s

def a(f=b):
    f("hello")

a()

这不是:

def a(f=b):
    f("hello")

def b(s):
    print s

a()

需要注意的是,这与关键字参数默认值是一个函数无关。它可以是在定义函数之前未定义的任何其他对象。当解释器遇到def writeChangelog时,没有_changelog_txt这样的东西。

在这种情况下,重新排序代码是一个不错的选择。

运行时的情况不同,因为在运行之前解释器已经遇到了所有defs。这就是为什么很少有人会在 python 中遇到这种问题。

【讨论】:

  • Facepalm - 我想到了,但我说“呃,不可能是这样的” - 这里有太多 Java :D
【解决方案2】:

作为 DrV 答案的补充:

在 Python 中,函数的签名是在解释器第一次看到它时评估的,而不是在调用时评估的。因此,就范围而言,您的代码相当于以下内容:

b = a
a = 1

输出:

b = a
NameError: name 'a' is not defined

希望您现在明白,为什么您的代码不起作用。

附带说明:虽然这种行为使默认参数表达式的计算范围更加明显,但它也是一个容易产生错误的来源,例如:

def foo(bar = []):
    bar.append(1)
    return bar

print(foo())
print(foo())

输出:

[1]
[1, 1]

这里,默认值始终是相同的列表——在所有foo 调用中——因为函数签名只被评估一次。解决方案是使用None 作为默认值并进行显式检查:

def foo(bar = None):
    if bar is None:
        bar = []
    bar.append(1)
    return bar

print(foo())
print(foo())

输出:

[1]
[1]

【讨论】:

    猜你喜欢
    • 2017-02-27
    • 2018-08-08
    • 2013-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多