【问题标题】:Why print statement is not pythonic? [closed]为什么打印语句不是pythonic? [关闭]
【发布时间】:2010-11-06 10:23:58
【问题描述】:

这个问题困扰了我很长一段时间(my previous question 证明了这一点):为什么 print(x)print x 更好(被定义为更 Pythonic)?

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

我想对这些观点提出反对意见:

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

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

【问题讨论】:

  • 我不确定 SO 是否适合进行关于 Python 是什么的哲学讨论。更适合那些有兴趣积极将其发展方向调整到版本 3 的人来回答。您可以在这里找到他们:python.org/dev
  • 部分是出于stackoverflow.com/questions/1003841/…的精神
  • SO 如何提供比 PEP 3105 更规范的答案?关于该决定,您还需要了解哪些信息?
  • SO 可以轻松地为稍微不同的问题提供更规范的答案。

标签: python python-3.x


【解决方案1】:

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

关于你的争论点:

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

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

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

对于初学者来说,操作符 print 可以 不属于一般应用 逻辑。对他们来说这是神秘的 算子是一个高潮 他们的节目。他们希望它看起来 不同。

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

所有的初学者书籍 现在描述基本的 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

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

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

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

【讨论】:

  • 根据我的原始帖子,我重视这个问题的答案,特别是如果这个答案也表明我的观点有多糟糕。仅供参考,你有我的投票,目前唯一的。是的,我将接受与您类似的帖子。
  • @ilya,我接受纠正,并为基于明显过于脆弱且无法支持的基础上的其他推断而道歉 - 抱歉。
【解决方案2】:

这就是我讨厌 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)"

hmm.. 那么这个 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 语句,然后改进它以使用日志记录或更好的东西是不优雅的。如果 print 像那些东西一样工作,特别是可以与高阶函数一起使用,那么它会比你不使用 real 日志记录或 real em> 调试器。

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    • 我很想接受一个最符合我想法的答案。我想知道这是否对其他人不礼貌。
    • 接受的标准差异很大,通常包括投票数。因此,接受最高投票的答案通常不是一个坏主意,当然也不是不礼貌的。 :)
    • 嗯,我希望对我的确切问题有一个规范的答案......但是是的,可以等待。
    【解决方案4】:

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

    【讨论】:

    • 正如我的第 4 点所说,我有兴趣让 print 比 sys.stdout.write() 做得更多
    • 我认为 write 和 format 字符串的组合符合 C 的 printf/sprintf 系列,它们经受住了时间的考验
    • @ilya,但是如何准确控制 print 的翻译方式。在我看来,这将取决于脚本的主机(解释器等)来确定如何处理输出。使用脚本写入 stdout 和 stderr 的主机似乎是实现这一点的最佳方式。
    • 我认为打印是一种更新手类型的东西,即被甚至对标准输出一无所知的人使用。
    【解决方案5】:

    这不是pythonic,因为语法应该是:

    stdout.append("Hello World")
    

    stdout += "hello world"
    

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

    说真的……

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

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

    【讨论】:

    • 我确信 str(stdout) 会产生一个字符串,根据定义,它不会以任何方式与输出连接。也许 stdout += 'Hello world!'会更接近你的意思。
    • @ilya - 我觉得我英国式的干巴巴的幽默感已经消失了。我会添加你的建议来增加幽默因素:)
    • 为什么,我想我明白了。我确实认为像你说的那样写有点像pythonic。
    猜你喜欢
    • 1970-01-01
    • 2023-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-16
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多