覆盖内置功能

use*_*519 9 python function built-in

我有一大堆使用"print"语句的代码.至于这样说:

print "foo"
Run Code Online (Sandbox Code Playgroud)

并不是

print("foo")
Run Code Online (Sandbox Code Playgroud)

我想改变输出.我可以在不改变所有印刷线的情况下这样做吗?例如,通过覆盖函数/语句?

Mar*_*ers 15

Python 直接支持你想要做的事情:

from __future__ import print_function
Run Code Online (Sandbox Code Playgroud)

顶部具有该行的任何模块都将该print语句视为函数,使代码与Python 2和3兼容.

这适用于只是print陈述; 你不能覆盖其他陈述.

这意味着你必须print()在该模块中的任何地方使用函数,但如果你愿意,你也可以提供自己的实现:

from __future__ import print_function
import __builtin__

def print(*args, **kwargs):
    __builtin__.print('Prefixed:', *args, **kwargs)

print('Hello world!')
Run Code Online (Sandbox Code Playgroud)

另一种选择是使用上下文管理器捕获打印的语句,将输出引导sys.stdout到您选择的内存中文件对象:

from contextlib import contextmanager
import sys
try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO


@contextmanager
def capture_sys_output():
    caputure_out = StringIO()
    current_out = sys.stdout
    try:
        sys.stdout = caputure_out
        yield caputure_out
    finally:
        sys.stdout = current_out
Run Code Online (Sandbox Code Playgroud)

print使用上下文管理器包装要捕获输出的任何块.以下是打印行前缀的示例:

with capture_sys_output as output:
    print 'Hello world!'

output = output.get_value()
for line in output.splitlines():
    print 'Prefixed:', line
Run Code Online (Sandbox Code Playgroud)

甚至提供包装:

from contextlib import contextmanager
import sys

class Prefixer(object):
    def __init__(self, prefix, orig):
        self.prefix = prefix
        self.orig = orig
    def write(self, text):
        self.orig.write(self.prefix + text)
    def __getattr__(self, attr):
        return getattr(self.orig, attr)     

@contextmanager
def prefix_stdout(prefix):
    current_out = sys.stdout
    try:
        sys.stdout = Prefixer(prefix, current_out)
        yield
    finally:
        sys.stdout = current_out
Run Code Online (Sandbox Code Playgroud)

并用作:

with prefix_stdout('Prefixed: '):
    print 'Hello world!'
Run Code Online (Sandbox Code Playgroud)

但要考虑到print语句通常将数据写入stdout单独的块中; 最后的换行符是一个单独的写.


unu*_*tbu 6

这会更改print语句的行为,而不会强制您更改

print "foo"

print("foo")
Run Code Online (Sandbox Code Playgroud)
import sys
_stdout = sys.stdout

class MyStream(object):
    def __init__(self, target):
        self.target = target

    def write(self, s):
        s = 'Foo : {!r}'.format(s)
        self.target.write(s)
sys.stdout = MyStream(sys.stdout)
print 'Hi'
sys.stdout = _stdout   # return print to its old behavior
Run Code Online (Sandbox Code Playgroud)

产量

Foo : 'Hi'
Run Code Online (Sandbox Code Playgroud)

这可以通过上下文管理器来实现,但如果您不想将print语句更改为print函数,则可能不希望将print语句包装在上下文管理器中.


因此,使用更好,更文明的方式

2to3 --write  --fix print test.py
Run Code Online (Sandbox Code Playgroud)

自动print将代码中的所有语句(例如上面的test.py)更改为print函数.然后,您可以通过重新定义print函数来更改行为:

from __future__ import print_function
import __builtin__

def print(*args, **kwargs): 
    __builtin__.print('Foo:', *args, **kwargs)
print('Hi')
Run Code Online (Sandbox Code Playgroud)

产量

Foo: Hi
Run Code Online (Sandbox Code Playgroud)