在编程语言中有两个很基础的概念,即方法(method)和函数(function)。如果达到了编程初级/入门级水平,那么你肯定在心中已有了初步的答案。

也许在你心中已有答案了

除去入参、返回值、匿名函数之类的正确的形式内容之外,你也许会说“函数就是定义在类外面的,而方法就是定义在类里面的,跟类绑定的”。

这种说法有没有问题呢?当然有!不然我就不会专门写这篇文章了,本文主要会来厘清这个问题。

在标准库inspect 中,它提供了两个自省的函数,即 ismethod() 和 isfunction(),可以用来判断什么是方法,什么是函数。

因此,本文想要先来研究一下这两个函数,看看 Python 在处理方法/函数的概念时,是怎么做的?

关于它们的用法,先看一个最简单的例子:

运行的结果分别是“True”和“False”,表明我们所定义的 test() 是一个函数,而不是一个方法。

这两个函数也可以用来检测自身,不难验证出它们都是一种函数:

那么,接下来的问题是:inspect 库的两个函数是什么工作原理呢?

先来看看 inspect 中的实现代码:

在源码中,我们看到了 isinstance() 函数,它主要用于判断一个对象(object)是否是某个类(class)的实例(instance)。

我们还看到了 types.FunctionTypetypes.MethodType ,它们指的就是目标类。继续点进去看源码:

# 摘自 types.py
def _f(): pass
FunctionType = type(_f) class _C:
def _m(self): pass
MethodType = type(_C()._m)

这里只是定义了两个空的 _f() 和 _m(),然后就使用了内置的 type() 函数。所以,我们完全可以把它们摘出来,看看庐山真面目:

梳理它们的关系,可以得到:

经过简化处理后,我们发现最关键的是两个问题:type() 函数如何判断出一个对象是 function 或 method 类?instance() 函数如何判断出一个对象是某个类的实例?

这两个内置函数都是用 C 语言实现的,这里我就不打算继续深究了……

但是,让我们再回头看看 inspect 中的注释,就会注意到一些端倪:

  • isfunction() 判断出的是用户定义的函数(user-defined function), 它拥有__doc__、__name__ 等等属性
  • ismethod() 判断出的是实例方法(instance method), 它拥有函数的一些属性,最特别的是还有一个 __self__ 属性

还是注释更管用啊,由此我们能得到如下的推论:

1、非用户定义的函数,即内置函数,在 isfunction() 眼里并不是“函数”(FunctionType)!

下面验证一下 len()、dir() 和 range():

事实上,它们有专属的类别(BuiltinFunctionType、BuiltinMethodType):

特别需要注意的是,内置函数都是builtin_function_or_method 类型,但是 range()、type()、list() 等看起来像是函数的,其实不然:

(PS:关于这点,我这篇文章 曾提到过,就不再展开了。)

2、一个类的静态方法,在 ismethod() 眼里并不是方法(MethodType)!

创建了类的实例后,再看看:

可以看出,除了 classmethod 之外,只有类实例的实例方法,才会被 ismethod() 判定为真!而静态方法,不管绑定在类还是实例上,都不算是“方法”!

有没有觉得很不可思议(或者有点理不清了)?

好了,回到本文开头的问题,我们最后来小结一下吧。

若以 inspect 库的两个函数为判断依据,则 Python 中的“方法与函数”具有一定的狭义性。在判断什么是函数时,它们并不把内置函数计算在内。同时,在判断什么是方法时,并非定义在类内部的都算,而是只有类方法及绑定了实例的实例方法才算是“方法”。

也许你会说,inspect 的两个判断函数并不足信,内置函数也应该算是“函数”,类里面的所有方法都应该算是“方法”。

我承认这种说法在广义上是可接受的,毕竟我们一直叫的就是“XX函数”、“XX方法”嘛。

但是,理论和广义概念只是方便人们的沟通理解,而代码实现才是本质的区别。也就是说,Python 在实际区别“方法与函数”时,并不是文中开头的简单说法,还有更多的细节值得关注。

看完本文,你有什么想法呢?欢迎一起交流。

学编程这么久,还傻傻分不清什么是方法(method),什么是函数(function)?的更多相关文章

  1. 学点经济学:M0、M1、M2、M3,傻傻分不清?(转载)

    来源:http://t.10jqka.com.cn/pid_97006727.shtml 学点经济学:M0.M1.M2.M3,傻傻分不清? 25,508人浏览 2018-08-03 11:06 常听人 ...

  2. 2021年了,`IEnumerator`、`IEnumerable`还傻傻分不清楚?

    IEnumerator.IEnumerable这两个接口单词相近.含义相关,傻傻分不清楚. 入行多年,一直没有系统性梳理这对李逵李鬼. 最近本人在怼着why神的<其实吧,LRU也就那么回事> ...

  3. bind,apply,call,caller,callee还傻傻分不清楚?

    先介绍每个的语法: 1. bind() 语法:fn.bind(thisObj[, arg1[, arg2[, ...]]]) fn:是想要改变this指向的函数 thisObj:表示fn中this指针 ...

  4. JDBC、ORM、JPA、Spring Data JPA,傻傻分不清楚?一文带你厘清个中曲直,给你个选择SpringDataJPA的理由!

    序言 Spring Data JPA作为Spring Data中对于关系型数据库支持的一种框架技术,属于ORM的一种,通过得当的使用,可以大大简化开发过程中对于数据操作的复杂度. 本文档隶属于< ...

  5. JS魔法堂:属性、特性,傻傻分不清楚

    一.前言 或许你和我一样都曾经被下面的代码所困扰 var el = document.getElementById('dummy'); el.hello = "test"; con ...

  6. Java:接口和抽象类,傻傻分不清楚?

    01. 来看网络上对接口的一番解释: 接口(英文:Interface),在 Java 编程语言中是一个抽象类型,是抽象方法的集合.一个类通过继承接口的方式,从而来继承接口的抽象方法. 兄弟们,你们怎么 ...

  7. [转帖]十分钟快速理解DPI和PPI,不再傻傻分不清!

    十分钟快速理解DPI和PPI,不再傻傻分不清! https://baijiahao.baidu.com/s?id=1605834796518990333&wfr=spider&for= ...

  8. 【华为敏捷/DevOps实践】7. 敏捷,DevOps,傻傻不分清楚【华为云技术分享】

    文:姚冬(华为云DevCloud首席技术布道师,资深DevOps与精益/敏捷专家,金融解决方案技术Leader,中国DevOpsDays社区核心组织者) 前言 敏捷是什么?DevOps是什么?两者有什 ...

  9. 傻傻分不清之 Cookie、Session、Token、JWT

    傻傻分不清之 Cookie.Session.Token.JWT 什么是认证(Authentication) 通俗地讲就是验证当前用户的身份,证明“你是你自己”(比如:你每天上下班打卡,都需要通过指纹打 ...

随机推荐

  1. Android模拟器不能上网的解决方法

    我原来一直不用Android的模拟器,因为这东西的多年前的印象真的是很糟糕——启动半个小时,不支持OpenGL.即使后来有了x86镜像,在HAXM的支持下快的飞起,也不想用,因为NDK还要编译x86的 ...

  2. vue中eslint报错的解决方案

    1,Newline required at end of file but not found. (eol-last) //文末需要一行 这个是报错: 这个是不报错的: 只需要在最后一行加上一空行即可 ...

  3. vue2.0中eventBus实现兄弟组件通讯

    我们知道,在vue中父子组件的通讯是通过props和自定义事件搞定的,简单那的非父子组件通讯用bus(一个空的Vue实例),针对中大型的项目会选择vuex,然而小项目的话,便捷的解决方案就是event ...

  4. django 登录、注册

    一.登录 1.在blogapp同级目录下新建一个userapp python manage.py startapp users 目录结构如下: 2.在主项目urls.py中新建users的includ ...

  5. python学习-练习题1巩固(随机数)

    1.生成随机数 random.random()生成一个0-1之前的随机数

  6. webpack学习(一):webpack的安装和命令行

    本教程可以学习到如下内容: 1.webpack的安装 2.利用webpack命令打包js文件 3.如何在js文件里面引用css并将css文件在页面里面生效 4.学习webpack相关的高级的一些参数, ...

  7. Natas12 Writeup(文件上传漏洞)

    Natas12: 文件上传页面,源码如下: function genRandomString() { $length = 10; $characters = "0123456789abcde ...

  8. LeetCode--179场周赛题解

    水题: class Solution { public: string generateTheString(int n) { string s; string a="a",b=&q ...

  9. Kubernetes实战总结 - 系统初始化

    设置系统主机名以及Host文件的相互解析 hostnamectl set-hostname k8s-master01 cat >> /etc/hosts <<EOF 192.1 ...

  10. XML的概述,.Dom4解析和SAX解析

    1.什么是XML XML 指可扩展标记语言(EXtensible Markup Language) html(hyper text markup langauge) XML 是一种标记语言,很类似 H ...