33

这个问题困扰了我很长一段时间(正如我之前的问题所证明的那样):为什么确切print(x)地更好(被定义为更pythonic)比print x

对于那些不知道的人,该print语句在 Python 3.0 中已更改为函数。正式文档在PEP 3105中,动机在Guido van Rossum 的电子邮件中。

对于这些观点,我想提出一个反对意见:

  1. 还有其他运算符,例如import我们写成语句的运算符,尽管它们的功能实际上与函数重复__import__
    • 对于初学者来说,算子print不属于一般的应用逻辑。对他们来说,神秘的操作员是他们计划的高潮。他们希望它看起来不一样。
    • 现在保证所有描述基本 Python 2.x 的初学者书籍都与第一个示例不同。当然,语言有时会发生变化,但这些变化对于新手来说通常不太明显。
    • 对我来说,print可以在应用程序级别复制的功能并不是很明显。例如,有时我想将来自控制台的打印重定向为模式 OS 对话框。
    • 虽然人们说很难将所有print语句重写为函数,但他们已经迫使每个 Python 2.x 开发人员在他们的所有项目中都这样做。很好,使用自动转换器并不难。
    • 如果是一个语句包装函数,那么每个喜欢拥有操作函数的能力的人print都会得到很好的服务。print__print__

那么,我们能否在 Stack Overflow 的页面上对这个问题给出一个规范的答案?

4

5 回答 5

58

在我看来,你的问题是一场辩论,而不是一个问题——你真的会接受一个表明你的断言有多么严重和严重错误的答案吗?!

关于你的辩论点:

还有其他的操作符,比如我们写成语句的 import,虽然它们的功能实际上是和一个函数重复的__import__

绝对错误:函数__import__(就像其他所有函数——和运算符一样)在“调用者”(包含它的代码)范围内不绑定任何名称——任何在“调用者范围”中绑定名称的“事物”必须是语句(就像赋值def、 和call)。您的“观点”似乎完全忽略了 Python 在语句和表达式之间绘制的极其深刻和关键的区别——人们可能有理由不喜欢这种区别,但最明显的是,忽略它是完全错误的。

Python 语句是 Python 编译器必须特别注意的事情——它们可能会改变名称的绑定,可能会改变控制流,和/或可能需要在某些条件下从生成的字节码中完全删除(后者适用于assert)。print是 Python 2 中此断言的唯一例外;通过从语句列表中删除它,Python 3 删除了一个异常,使一般断言“保持不变”,因此是一种更常规的语言。特殊情况不足以打破规则长期以来一直是 Pythonic 的信条(import this在交互式解释器的>>>提示看到显示的“Python 之禅”),并且对语言的这种更改消除了对这一原则的违反,该原则由于早期的错误设计决定而不得不保留多年。

对于初学者来说,算子打印不属于一般的应用逻辑。对他们来说,神秘的操作员是他们计划的高潮。他们希望它看起来不一样。

尽早纠正初学者的误解是一件非常好的事情。

现在保证所有描述基本 Python 2.x 的初学者书籍都与第一个示例不同。当然,语言有时会发生变化,但新手通常不太容易看到变化。

语言很少以深度和向后不兼容的方式发生变化(Python 大约十年一次),并且很少有语言特性“对新手非常可见”,因此观察的总数很小——但即使在那个微小的指南针内,我们也可以轻松地找到反例,其中一个对初学者来说高度可见的功能设计得非常糟糕,以至于删除它是非常值得破坏的。例如,现代的 Basic 方言,如 Microsoft 的 Visual Basic,不使用明确的用户输入的行号,这是一个既可怕又高度可见的“功能”,因为它在 Basic 的早期方言中是强制性的。Lisp 的现代变体(从 Scheme 开始)不使用动态作用域,

对我来说,打印功能可以在应用程序级别上复制并不是很明显。例如,有时我想将来自控制台的打印重定向为模式 OS 对话框。

不确定我是否遵循这个“点”。只需更改sys.stdout为您最喜欢的伪文件对象并重定向到您心中的内容——您可以选择猴子修补内置函数print(这是您在 Python 2 中从未有过的),但没有人会扭动您的手臂并强迫您这样做.

虽然人们说很难将所有打印语句重写为一个函数,但他们已经迫使每个 Python 2.x 开发人员在他们的所有项目中都这样做。很好,使用自动转换器并不难。

2to3工具确实解决了所有这些简单的表面不兼容问题——不费吹灰之力(无论如何它都需要运行才能处理更多问题print,所以人们确实广泛使用它)。那么,你在这里的“重点”是什么?

如果 print 是一个语句包装函数print,那么每个喜欢能够操作函数 print 的人都会得到同样的服务。

这种安排本身不会删除不必要的关键字(尤其是不合理的不规则性,正如我上面解释的那样:一个没有充分理由成为语句的语句,因为编译器绝对不需要特别以任何方式、形状或形式意识到它!)。我还不清楚拥有这样一个底层函数是否会增加任何真正的价值,但如果你有真正的用例,你当然可以在 Python Ideas 邮件列表中提出这个案例——这样一个底层函数,如果被证明确实很珍贵的话, 可以被改造以供printPython 2.7 中的语句和printPython 3.2 中的函数使用。

然而,考虑一个典型的情况,在这种情况下,人们可能想要对内置 进行猴子补丁print:添加关键字参数以允许进行花哨的调整。您显然提出的函数将如何从语句中__print__获取这些 KW 参数?__print__一些更时髦的语法比恐怖的>> myfile逗号和尾随的逗号......?!作为print函数,关键字参数遵循适用于每个函数和函数调用的完全正常和普通的规则——幸福!

因此,总而言之,print作为一个函数,它更像 Pythonic,因为它消除了异常、特殊情况以及任何对奇怪的特殊语法的需求——简单、规律和统一是 Python 的商标。

于 2009-06-28T02:15:33.663 回答
11

这就是我讨厌 2.x 中的 print 语句的原因。

>>> something()
<something instance at 0xdeadbeef>
>>> print something()
<something instance at 0xdeadbeef>

没用的东西没有用__str__,好吧,我可以处理,再看一下。

>>> dir(something())
['foo', 'bar', 'baz', 'wonderful']
>>> help(something().foo)
"foo(self, callable)"

嗯 .. 那可调用的是否需要参数?

>>> something().foo(print)
    something().foo(print)
                        ^
SyntaxError: invalid syntax
>>> something().foo(lambda *args: print(*args))
    something().foo(lambda *args: print(*args))
                                      ^
SyntaxError: invalid syntax

所以......我必须定义一个要使用的函数

>>> def myPrint(*args): print *args
    def myPrint(*args): print *args
                              ^
SyntaxError: invalid syntax
>>> def myPrint(*args): print args
...
>>> myPrint(1)
(1,)

颤抖,或使用sys.stdout.write,几乎一样笨拙,因为它的行为与print. 它看起来也不同,这意味着我几乎永远不会记得它存在。

print在简短的一次性类型工具中使用语句,然后改进它以使用日志记录或更好的东西是不雅的。如果 print 像那些东西一样工作,特别是可以与高阶函数一起使用,那么它会比你不使用真正的日志记录或真正的调试器时使用的东西更好。

于 2009-06-28T02:44:21.047 回答
8

print语句还带有>>用于打印到特定文件的不寻常语法。Python 中没有其他语句具有这种语法,因此这种方式很不寻常。

我相信您是对的,该print语句的大多数问题都可以通过引入__print__函数来解决。

于 2009-06-27T23:34:11.120 回答
6

我发现 GvR 的“打印是唯一具有专用声明的应用程序级功能”令人信服。Python 是一种通用语言,不应该有将输出到流的语句作为运算符或关键字。

于 2009-06-27T23:36:24.283 回答
3

它不是 Pythonic,因为语法应该是:

stdout.append("Hello World")

或者

stdout += "hello world"

免责声明:我真的很喜欢 Python。

严肃地说...

我认为 Python 的对象模型和“自己实现”处理属性可见性之类的方法非常棒。我认为这种“一切都是对象”的 OOP 方法,甚至将对象定义为对象结构的集合也是非常清晰的。

我担心 Python 会成为一种无法以清晰的方式表达其意图的语言......我不想看到这些原则的美丽陷入对已经非常规的语法表示的过度思考。有点像Lisp,结构优美,语法严酷,恕我直言。

于 2009-06-27T23:36:41.240 回答