为什么print语句不是pythonic?

ily*_* n. 33 python python-3.x

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

对于那些不知道的人,print声明在Python 3.0中被改为函数.正式文件在PEP 3105中,动机在Guido van Rossum的电子邮件中.

对于这些观点,我想提出一个对立点:

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

那么,我们能不能在Stack Overflow页面上对这个问题做出规范的回答?

Ale*_*lli 57

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

关于你的辩论要点:

还有其他运算符,例如我们作为语句编写的import,尽管它们的功能实际上与函数重复 __import__

绝对错误:函数__import__(就像所有其他函数一样 - 和运算符一样)在"调用者"(包含它的代码)范围内绑定任何名称 - 任何绑定"调用者范围"中名称的"thingie" 必须是声明(就像赋值一样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开始)不使用动态作用域,这是一种令人遗憾的高度可见的错误(通常在其代码中表现为难以理解的错误),对于初学者来说,基本上只要他们开始在Lisp中编写函数1.5(我曾经是一个初学者,可以证明它有点糟糕).

对我来说,在应用程序级别上可以复制打印功能并不是很明显.例如,有时我想从控制台重定向打印作为模态操作系统对话框.

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

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

2to3工具确实可以处理所有这些容易出现的表面不兼容问题 - 没有汗水(无论如何都需要运行它来照顾更多print,所以人们会广泛使用它).那么,你的"观点"在这里是什么?

如果print是一个包装函数print的语句,那么每个喜欢有能力操作函数打印的人都会得到很好的服务.

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

但是,考虑一个典型的情况,人们可能想要修补内置print函数:添加关键字参数以允许花哨的调整.__print__你明显提出的函数如何从__print__声明中得出那些KW参数?还有一些比较恐怖>> myfile和尾随逗号的更有趣的语法......?!随着print作为一个功能,关键字参数遵循这一点适用于完全正常的,普通的规则每个函数和函数调用-极乐!

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

  • @ilya,我站出来纠正并道歉,因为基于明显过于脆弱和不可支持的基础推断 - 抱歉. (12认同)
  • 根据我原来的帖子,我重视这个问题的答案,特别是如果这个答案也表明我的观点有多糟糕.仅供参考,你有我的投票,这是目前唯一的投票.是的,我将接受一个类似于你的帖子. (7认同)

Sin*_*ion 11

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

>>> something()
<something instance at 0xdeadbeef>
>>> print something()
<something instance at 0xdeadbeef>
Run Code Online (Sandbox Code Playgroud)

毫无价值的对象没有用__str__,很好,我可以处理,再看一下.

>>> dir(something())
['foo', 'bar', 'baz', 'wonderful']
>>> help(something().foo)
"foo(self, callable)"
Run Code Online (Sandbox Code Playgroud)

嗯..那个可调用的参数也是如此?

>>> something().foo(print)
    something().foo(print)
                        ^
SyntaxError: invalid syntax
>>> something().foo(lambda *args: print(*args))
    something().foo(lambda *args: print(*args))
                                      ^
SyntaxError: invalid syntax
Run Code Online (Sandbox Code Playgroud)

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

>>> def myPrint(*args): print *args
    def myPrint(*args): print *args
                              ^
SyntaxError: invalid syntax
>>> def myPrint(*args): print args
...
>>> myPrint(1)
(1,)
Run Code Online (Sandbox Code Playgroud)

颤抖,或使用sys.stdout.write,几乎像cludgy,因为它有非常不同的行为print.它看起来也不同,这意味着我几乎永远不会记得它存在.

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


Gre*_*ill 8

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

我相信你是对的,print声明的大多数问题都可以通过引入__print__函数来解决.


Jac*_*cob 6

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