【问题标题】:sys.stdout as default function argumentsys.stdout 作为默认函数参数
【发布时间】:2017-08-03 09:07:00
【问题描述】:

假设我们有以下虚拟函数:

import sys

def writeline(text, stream=sys.stdout):
    stream.write(text + '\n')

with open('/path/to/file', 'w') as f:
    # writes to /path/to/file
    writeline('foo', f)

# writes to standard output
writeline('bar')

鉴于 Python 在定义时评估函数的默认参数,将 sys.stdout 设置为默认参数是否安全,或者它可能会产生意想不到的副作用?

【问题讨论】:

标签: python stdout default-value sys


【解决方案1】:

我想到的一个问题是,您有时想自己将sys.stdout 重定向到文件(或管道、设备等)

例如,您的主程序可能如下所示:

if __name__ == '__main__':
    if len(sys.argv) > 1:
        sys.stdout = open(sys.argv[1],'w')
    try:
        # ... run the program
    finally:
        if len(sys.argv) > 1:
            sys.stdout.close()

如果你希望你的程序记录到一个文件,如果你提到了一个文件(比如python3 file.py logfile.log),这可能很有用。现在,由于您设置了sys.stdout,您的writeline 方法将不会注意到该修改。

因此我认为这样写更安全:

def writeline(text, stream = None):
    if stream is None:
        stream = sys.stdout
    stream.write(text + '\n')

一般来说,将不可变 对象设置为默认参数(如NoneFalse(1,) 等)可能是一个不错的建议。只有在极少数情况下,Python 才会故意使用不可变的(或可能更改引用的)。

如果您确定不会将sys.stdout 重定向到文件、管道等。这是安全的。

【讨论】:

  • 好点。我知道将 immutable 对象设置为默认参数更好的原因,但我认为在这种情况下没有必要,因为我没有考虑sys.stdout 本身是允许的可能性改变。
【解决方案2】:

当对命名参数的 constant 值有疑问时,最常用的习惯用法是将参数设置为 None,因此始终在运行时针对以下值进行解析当前调用时间:

def writeline(text, stream=None):
    if stream is None:
        stream = sys.stdout
    stream.write(text + '\n')

【讨论】:

    【解决方案3】:

    如果你使用 Python 3 的 print 函数,如果 file 参数是 None 输出将照常打印到 stdout。所以你可以像这样设置默认值None

    def write_something(items, outfile=None):
        for item in items:
            print(item, file=outfile)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-03
      • 1970-01-01
      • 1970-01-01
      • 2019-09-11
      • 2010-10-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多