void 是编程语言中最常见的关键字之一,从字面上理解,它是“空的、空集、空白”的意思,最常用于 表示函数的一种返回值类型。

维基百科上有一个定义:

The void type, in several programming languages derived from C and Algol68, is the type for the result of a function that returns normally, but does not provide a result value to its caller.

在 C、Algol68 及它们所派生的几种编程语言中,void 类型是函数正常返回的一种类型,但是不会给调用者返回一个值。

简单来说,void 是一种类型(type),但是没有具体的值(value)。

这到底是什么意思呢?

以 Python 的几种常见类型为例,我们可以从对比中看出规律:int 是一种表示整数的类型,它有无限个可能的整数值;bool 是一种布尔类型,它有两个可能的值(True 和 False);NoneType 是一种表示 None 的类型,它只有一个值(None)。

至于 void,它是一种更为抽象的特殊类型,但是不包含任何值。

介绍完概念上的含义,我们就可以进入正题了。标题中的问题可以进一步分解成两个:

  • 其它语言为什么要使用 void 关键字?
  • Python 为什么不设计出 void 关键字?

对于第一个问题,我们以 C/C++ 为例,先看看 void 的两种使用场景(PS:此处只考虑函数的用法,不考虑指针的用法,因为 Python 没有指针):

当 void 用在函数的参数位置时,它表示该函数不需要传参。

最初 C 语言的f() 表示参数数量不确定,为了另外表达“不需要参数”的语义,所以引入f(void) 作为限定。后来的语言(包括 Python)基本不在参数中使用 void,而是直接用f() 表示不需传参。C++ 为了兼容 C,所以才同时支持这两种语法。

当 void 用在函数前作修饰时,它表示该函数没有返回值。

在 C 语言中,若不声明返回类型,则f() 函数在编译后会返回整型的值。为了避免混乱,当不需要返回值时,就使用void f() 来作限定。

同时,更主要的是,它还起到了占位符的作用,表明一个函数的类型是已知的,这对代码可读性和编译都有所帮助。

void 作为函数的空返回值类型,这种用法在 C++/Java 中也被继承了。另外,在 Javascript 中也有 void 的身影,只不过它成了一种操作符,起到了完全不同的作用,此处不表。

但是,Python 从头到尾都没有 void 关键字。

为什么会这样?难道是因为在 Python 中不存在其它语言所面对的问题么?还是说,Python 中有自己的一套解决方案?

仍以跟函数相关的两种用法为例作分析吧。

在表示函数不需传参时,f(void) 这种写法根本就是多余的,所以 Python 使用了最简单明了的无参式写法f()

至于返回值类型的用法,在我们定义出一个函数时,例如最简单的def func():pass ,为了让它的调用结果func() 是一个合法的对象,那它必须具有一个有效的类型(type)。

这应该是以类型为基的编程语言都会遇到的共性问题,Python 也不例外。

这个时候,如果函数本身没有显式地 return 出一个对象的话,就有两种可能的解决办法:

  • 方法一,即声明该函数为 void 类型,像 C 和其它语言所做的那样,只要能通过类型检查即可
  • 方法二,则是 Python 所用的方法,即令解释器隐式地返回一个 None 对象,也就是令函数默认得到一个 NoneType 类型,再用于类型检查(PS:Javascript 也类似,只不过它默认返回的是 undefined,它不是一个对象,而是一种表示“未定义”的类型,类似于 void)

简单而言,Python 的设计思路是直接复用已有的 NoneType 类型,并让解释器来填补缺失掉的函数类型。

关于 Python 解释器的这个隐式填补过程,我已在上一篇《Python 函数为什么会默认返回 None?》文章详细分析过,感兴趣的同学可去查阅。

这样做的好处至少有两点:一是没有引入新的 void 类型和关键字;二是不需要程序员在函数前声明返回类型,这就跟有显式返回值的写法保持了一致。

试想一下,如果 Python 不让函数默认有返回值的话,就可能要写成 void def func():... 这样的形式,那它就变成了函数定义时的一种特例。与另一种特例函数相比,即异步函数asyc def func():... ,就可能引起混乱。

总体而言,Python 似乎认为 void 空类型不是那么有存在的必要,似乎 NoneType 类型就足够了,而当缺少返回值时,让解释器统一注入是极为方便的,因此才出现了我们看到的现状。

至此,文章标题的问题算是圆满回答了。

最后,让我们开始进入 ending 吧:本文明面上是以“Python 为什么没有 void 关键字”为切入点,然而,它实际上瞄准的却是“Python 为什么需要返回 None”的问题。

在《Python 函数为什么会默认返回 None?》这篇文章中,我介绍了 Python 中函数默认返回 None 的机制,它是属于“how can”的内容。但是为什么要默认返回 None 呢?这则是属于“why need”或者“why should”的问题,而它需要从 void 关键字的缺失开始谈起……

那么,为什么 Python 没有 void 关键字呢?请往上翻,重新阅读本文……

本文属于“Python为什么”系列(Python猫出品),该系列主要关注 Python 的语法、设计和发展等话题,以一个个“为什么”式的问题为切入点,试着展现 Python 的迷人魅力。所有文章将会归档在 Github 上,项目地址:https://github.com/chinesehuazhou/python-whydo

Python 为什么没有 void 关键字?的更多相关文章

  1. python基础之常用关键字总结

    前言 到python3.6为止,python内置的关键字有33个,比python2.7的版本多了2个.下面总结一下python3的关键字的使用. python内置关键字 解释器在加载上下文的时候,如果 ...

  2. js的delete和void关键字

    delete关键字   delete关键字的作用: 删除对象的属性 语法:delete 对象.属性 可以删除没有使用var关键字声明的全局变量(直接定义在window上面的属性) delete关键字的 ...

  3. Python:笔记(7)——yield关键字

    Python:笔记(7)——yield关键字 yield与生成器 所谓生成器是一个函数,它可以生成一个值的序列,以便在迭代中使用.函数使用yield关键字可以定义生成器对象. 一个例子 我们调用该函数 ...

  4. C语言void关键字的深刻含义

    C语言void关键字的深刻含义 .概述 本文将对void关键字的深刻含义进行解说,并详述void及void指针类型的使用方法与技巧. .void的含义 void的字面意思是“无类型”,void *则为 ...

  5. C语言学习笔记--void关键字

    1.C语言中Void关键字的含义 void 修饰函数返回值和参数——为了表示“无”,如果函数没有返回值,那么应该将其声明为 void,同样的,如果函数没有参数,也应该声明其参数为 void //f() ...

  6. Python——函数的命名关键字参数

    命名关键字参数 对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数.至于到底传入了哪些,就需要在函数内部通过kw检查. 仍以person()函数为例,我们希望检查是否有city和job参数: ...

  7. Python学习笔记-Day3-python关键字

    1.and 逻辑与 2.assert 判断某个条件是否为真,如果为假,抛出错误 3.break跳出for,while循环 4.class 类定义 5.continue 跳出本次循环,执行下次循环 6. ...

  8. python函数 位置参数,关键字参数,可变参数优先级

    def fun(arg,args=1,*arg,**keywords): python 一共有这四类参数,第一类最常见,不用多说,第二类,关键字参数,python能通过关键字找到参数,python函数 ...

  9. (转) Python Generators(生成器)——yield关键字

    http://blog.csdn.net/scelong/article/details/6969276 生成器是这样一个函数,它记住上一次返回时在函数体中的位置.对生成器函数的第二次(或第 n 次) ...

随机推荐

  1. Andriod开发---《横竖屏切换时 Activity的生命周期的总结》

    横屏切换竖屏Activity的生命周期详解,下面分析一下切换时具体的生命周期: 1.新建一个Activity,并把各个生命周期打印出来 2.运行Activity,得到如下信息 onCreate--&g ...

  2. sed打印包含一个字符串的行到包含另一个字符串的行解答

    sed -n '/字符串1/,/字符串2/p' filename  这个命令为什么有时候打印不出来想要的东西,例如:sed -n '/root/,/adm/p'  /etc/passwd      我 ...

  3. layui常用插件(二) 时间插件

    日期和时间 html <div class="layui-inline"> <!-- 注意:这一层元素并不是必须的 --> <input type=& ...

  4. queue stack for STL

    前不久发现自己vector有些不会了,于是想起了queue和stack. 有一个小故事,,,某天我跟自己打赌我queue没有写博园,结果打开一看竟然不知什么时候写过了,而且(QAQ)还有一定的浏览量了 ...

  5. 在sharepoint 2010创建级联下拉菜单

    SPServices是一个jQuery库,它提取SharePoint Web服务,并使其更容易使用.它可以使用不同的Web服务操作提供更有用且很酷的功能.它完全安装在客户端,不需要服务器. 用SPSe ...

  6. Python os.stat() 方法

    概述 os.stat() 方法用于在给定的路径上执行一个系统 stat 的调用.高佣联盟 www.cgewang.com 语法 stat()方法语法格式如下: os.stat(path) 参数 pat ...

  7. PHP array_merge_recursive() 函数

    实例 把两个数组合并为一个数组: <?php$a1=array("a"=>"red","b"=>"green&q ...

  8. PHP str_shuffle() 函数

    实例 随机地打乱字符串中的所有字符: <?php高佣联盟 www.cgewang.comecho str_shuffle("Hello World");?> 定义和用法 ...

  9. QDC DAY1

    暴毙了,比较自闭的心理,有点崩溃.. LINK:幸福 一道曾经的我肯定能写出来的 但是我心态崩了 所以没有推出来. 当然 还是 我比较垃圾 但同时也不垃圾 ... 求 $T_n =\displayst ...

  10. 剑指 Offer 53 - II. 0~n-1中缺失的数字

    本题 题目链接 题目描述 我的题解 二分法 思路分析 排序数组中的搜索问题,首先想到二分法 当nums[center] > center 时,缺少的数在左区间 当nums[center] = c ...