Python 覆盖内置函数
我有一大块使用“print”语句的代码。这样说:Python 覆盖内置函数,python,function,built-in,Python,Function,Built In,我有一大块使用“print”语句的代码。这样说: print "foo" 而不是 print("foo") 我想改变输出。我可以在不更改所有打印行的情况下执行此操作吗?例如,通过覆盖Python 2.x中的函数/语句?,print是一条语句,因此可以不使用paren调用它。显然你在用这个 无法覆盖内置的打印语句 但是,它将其输出写入sys.stdout。也许您可以使用具有.write方法的某个对象覆盖sys.stdout,如下所示: import sys from StringIO impo
print "foo"
而不是
print("foo")
我想改变输出。我可以在不更改所有打印行的情况下执行此操作吗?例如,通过覆盖Python 2.x中的函数/语句?,
print
是一条语句,因此可以不使用paren调用它。显然你在用这个
无法覆盖内置的打印语句
但是,它将其输出写入sys.stdout
。也许您可以使用具有.write方法的某个对象覆盖sys.stdout,如下所示:
import sys
from StringIO import StringIO
s = StringIO()
sys.stdout = s
print "Hmmm."
assert s.getvalue() == "Hmmm.\n"
Python直接支持您想要做的事情:
from __future__ import print_function
任何在顶部有该行的模块都会将print
语句作为函数处理,从而使代码与Python 2和Python 3兼容
这只适用于打印语句;不能重写其他语句
这意味着您必须在该模块的任何地方使用print()
,但如果您愿意,也可以提供自己的实现:
from __future__ import print_function
import __builtin__
def print(*args, **kwargs):
__builtin__.print('Prefixed:', *args, **kwargs)
print('Hello world!')
另一个选项是使用上下文管理器捕获打印的语句,将输出从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
并使用上下文管理器包装要捕获的所有块打印
输出。以下是为打印行添加前缀的示例:
with capture_sys_output as output:
print 'Hello world!'
output = output.get_value()
for line in output.splitlines():
print 'Prefixed:', line
甚至提供包装:
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
并用作:
with prefix_stdout('Prefixed: '):
print 'Hello world!'
但是要考虑到,print
语句通常将数据以单独的块写入stdout
;末尾的换行是一个单独的写操作。在Python 2中,有一个print语句,它是一种语言构造。因此,您将无法覆盖其行为
在Python3和Python2中,如果明确地启用它,那么就有了print函数。它确实需要括号,因此打印“foo”将不起作用,但您可以重新定义它的作用:
>>> from __future__ import print_function # for Python 2
>>> oldPrintFunction = print
>>> def print (*args, **kwargs):
oldPrintFunction('I am a changed print function')
oldPrintFunction(*args, **kwargs)
>>> print('foo')
I am a changed print function
foo
这将更改print
语句的行为,而不强制您进行更改
打印“foo”
到
屈服
Foo : 'Hi'
Foo: Hi
这可以通过上下文管理器来解决,但是如果您不想将print
语句更改为print
函数,您可能也不想将print
语句包装到上下文管理器中
因此,一个更好、更文明的方法是使用
2to3 --write --fix print test.py
自动将代码中的所有print
语句(如上面的test.py)更改为print
函数。然后,您可以通过重新定义print
功能来更改行为:
from __future__ import print_function
import __builtin__
def print(*args, **kwargs):
__builtin__.print('Foo:', *args, **kwargs)
print('Hi')
屈服
Foo : 'Hi'
Foo: Hi
你想让你的代码与python 3兼容吗?你说的改变输出是什么意思?如果这是为了转换成python 3,工具会自动处理。实际上,你可以。请注意,只打印语句,但您可以。注意,这也会改变前面提到的大块代码调用的代码所执行的所有标准输出操作。这不仅仅局限于上述代码的范围。@RemcoGerlich:是的,真的。啊,然后他可以继续覆盖内置代码。我还是希望切换sys.stdout,但谁知道呢。问题是,在这种情况下,他必须将所有打印语句更改为使用parens,而更改所有打印语句正是他试图避免的。@RemcoGerlich:但这比使用全局“swap outstdout
”锤子更容易维护。@RemcoGerlich,最好是显式的,使用print函数(并一次性替换代码),而不是面对全局变量更改的隐式后果。太完美了!正是我想做的!非常感谢。