资讯专栏INFORMATION COLUMN

为什么print在Python 3中变成了函数?

taoszu / 1332人阅读

摘要:如果你以逗号为分隔符,传递额外的参数,这些参数会被传递至函数,最终打印时每个参数之间会空一格。从上面的示例代码中我们就可以看出,使用函数有明显的好处与使用语句相比,我们现在能够指定其他的分隔符和结束符。这就是为什么将变成函数的原因。

本文首发于编程派的微信公众号。

原作者:Brett Cannon

原文链接:http://www.snarky.ca/why-print-became-a-function-in-python-3

译者:EarlGrey@编程派

在Python 2中,print是一个语句(statement);而在Python 3中变成了函数(function)。很多Python用户都会问,为什么Python 3将print变成了函数呢?本文就是Python核心开发者Brett Cannon对此的解释。

今年初Python决定迁移到Github,就是由Brett Cannon征求Python社区的意见后作出的。他对此也作出了解释。

print语句与print函数的区别 print语句

在Python 2中,print语句最简单的使用形式就是print A,这相当于执行了sys.stdout.write(str(A) + " ")。如果你以逗号为分隔符,传递额外的参数(argument),这些参数会被传递至str()函数,最终打印时每个参数之间会空一格。例如,print A, B, C相当于sys.stdout.write(" ".join(map(str, [A, B, C])) + " ")。如果print语句的最后再加上一个逗号,那么就不会再添加断行符( ),也就是说:print A相当于sys.stdout.write(str(A))

从 2.0版本开始,Python引入了print >>的语法,作用是重定向print语句最终输出字符串的文件。例如,print >> output, A相当于output.write(str(A) + " ")

print函数

如果用Python来实现print函数,它的函数定义应该是这样的:

import sys

def print(*objects, sep=None, end=None, file=None, flush=False):
    """A Python translation of the C code for builtins.print().
"""
    if sep is None:
        sep = " "
    if end is None:
        end = "
"
    if file is None:
        file = sys.stdout
    file.write(sep.join(map(str, objects)) + end)
    if flush:
        file.flush()

从上面的代码中,我们可以发现:Python 3中的print函数实现了print语句的所有特性。

print A == print(A)
print A, B, C == print(A, B, C)
print A, == print(A, end="")
print >> output, A == print(A, file=output)

从上面的示例代码中我们就可以看出,使用print函数有明显的好处:与使用print语句相比,我们现在能够指定其他的分隔符(separator)和结束符(end string)。

关键在于灵活性

将print变成函数的真正巧妙之处在与灵活性,但这点并不容易被人发觉。print成为函数之后,给Python用户和Python开发团队带来了很大的灵活性。对于用户来说,这可以让你把print当作表达式(expression)使用;相比之下,print语句就只能作为语句使用。举个例子,假设你想在每一行后面打印一个省略号(ellipsis),表示这行尚未结束。使用print语句的话,你有两种选择:

# 手动实现 ...
print A, "..."

# 可复用的实现(这种方式也适用于print函数) ...
def ellipsis_print(*args):
    for arg in args:
        print arg, "",
    print "..."

但是在Python 3中,你可以选择更好的解决方式:

# 手动实现 ...
print(A, end="...
")

# 多个可复用的解决方案,利用print语句无法实现...
ellipsis_print = lambda *args, **kwargs: print(*args, **kwargs, end="...
")
# 或者 ...
import functools
ellipsis_print = functools.partial(print, end="...
")

换句话说,变成函数之后,print就可以组件化了,作为语句的print是无法支持的。还有,你还可以编写自己喜欢的print函数,将其赋值给builtins.print,就可以覆盖掉自带的函数实现了。这一点在Python 2中是不可能实现的。

对于Python开发团队来说,他们不必再从语法层面来实现print的相关功能了。例如,如果你想让print语句也一样可以灵活地支持指定分隔符,你要怎样去实现呢?这会是一个相当难解决的设计难题。但是如果print变成了函数,只需要新增一个参数就解决了。在Python中,函数可以接受任意数量的参数,这比从底层实现语法带来的灵活性要大的多。

我们还要注意,语法实现应该仅限于那些非这样做不可的功能,或者是以语法形式实现后,大幅提高了可读性的功能。在print这个案例中,print Aprint(A)之间的区别可以忽略不计,因此并没有影响可读性。而且,由于我们能够完全将print语句替换为函数,对于Python语言的功能性也没有损失。这就是为什么将print变成函数的原因。


欢迎大家扫描下方二维码关注我的公众号“编程派”,谢谢支持!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/37749.html

相关文章

  • Python装饰器

    摘要:一引用书流畅的书二基本概念问题装饰器是什么解答严格来说,装饰器只是语法糖,装饰器是可调用的对象,可以像常规的可调用对象那样调用,特殊的地方是装饰器的参数是一个函数问题装饰器有什么特性解答装饰器有个特性,一是可以把被装饰的函数替换成其他函数, 一, 引用 [书] 流畅的Python [书] Effective Python 二, 基本概念 showImg(https://segme...

    aisuhua 评论0 收藏0
  • 记录我的Python学习笔记

    摘要:本文是通过廖雪峰的网站学习而整理的真的是很好的教程,省得我花钱买书了,然后我没有去再整理总结语法,而是直接通过写出代码段来体现自己的学习,也方便以后的快速复习回顾。 不想再像以前那样,什么都从头开始学习语法、总结语法,这样反而会过分纠结于语法,耽误了开发,毕竟语言的主要属性是工具,次要的属性是语言本身。 所以还是先熟练使用语言去进行开发,等足够熟悉了,再去研究语言本身(编译原理……)。...

    lijy91 评论0 收藏0
  • 流畅的python读书笔记-第七章-函数装饰器和闭包

    摘要:函数装饰器和闭包严格来说,装饰器只是语法糖。何时执行装饰器它们在被装饰的函数定义之后立即运行。装饰器突出了被装饰的函数的作用,还便于临时禁用某个促销策略只需把装饰器注释掉。 函数装饰器和闭包 严格来说,装饰器只是语法糖。如前所示,装饰器可以像常规的可调用对象那样调用,其参数是另一个函数。有时,这样做更方便,尤其是做元编程(在运行时改变程序的行为)时。 Python何时执行装饰器 它们在...

    Hydrogen 评论0 收藏0
  • 关于函数参数传递,80%人都错

    摘要:另外说下,函数的返回值,也相当于是一次赋值。只不过,这时候是把函数内部返回值所指向的对象,赋值给外面函数的调用者输出函数结束后,这个标签虽然不存在了,但所指向的对象依然存在,就是指向的新对象。 还记得上一次关于变量作用域文章 : Crossin:全菊变量和菊部变量zhuanlan.zhihu.comshowImg(https://segmentfault.com/img/remote/...

    X_AirDu 评论0 收藏0
  • Python: 陌生的 metaclass

    摘要:但一般情况下,我们使用类作为元类。那么,元类到底有什么用呢要你何用元类的主要目的是为了控制类的创建行为。当然,有很多种做法,这里展示用元类的做法。当你创建类时,解释器会调用元类来生成它,定义一个继承自的普通类意味着调用来创建它。 元类 Python 中的元类(metaclass)是一个深度魔法,平时我们可能比较少接触到元类,本文将通过一些简单的例子来理解这个魔法。 类也是对象 在 Py...

    miya 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<