为什么Python类成员的调用和声明必须有"this"?
Python的这种设计是作者从Modula-3中借鉴来的,在后面使用的情况看来,这个设计也是比较成功的。我们对比Python和C++讨论一下这个问题:

Modula-3是上世纪80年代末数字设备公司(DEC)系统研究中心(SRC)和Olivetti研究中心(ORC)设计的一门语言。
尽管这门语言没有在业界广泛的应用起来,但这么语言对后面被发明的Java, Python, Caml, C# 都产生了很多的影响

1.首先,调用的时候要求指定"this",让我们更明确的区分调用的是一个成员变量、函数或者是一个局部变量、函数。
当我们读到self.x或者self.meth(),即使我们不知道class的定义也能100%确定这里调用的是一个成员变量或者方法。我们设想一下,在C++中,我们还可以通过查看并排除所有的局部变量的方式去确认变量是成员变量(假设全局变量很少见,即使出现也是"g_"这种很容易辨认的)。
而在Python中,由于变量不需要额外的定义,这个办法就失效了,唯一的办法就只有看class的定义,所以this就成了必须的。 很多C++和Java的编码规范中会规定成员函数或变量要有m_前缀,我们也可以看到这种编码规范是十分必要的。
2.其次,由于this这个对当前实例的强制显式引用,Python不需要引入任何新的语法就可以引用或者调用其它类(包括父类)的成员变量和函数。
在C++中,如果我们想要在子类中调用父类的函数,我们需要用到::这个运算符;在Python中我们这么写baseclass.methodname(self, <argument list>)。Python的这种语法在实现子类的__init__()时特别有用,例如我们经常需要在子类中override父类的函数并且调用父类函数自身。
3.最后,就是性能上的些许考量:在Python的语言定义中,局部变量就是在函数体中赋值,并且没有在全局显式的声明过的变量。
当然在语言设计上,我们有很多的办法去告诉解释器、编译器某个变量赋值是针对一个局部变量还是一个成员变量,但出于解释性语言的性能考虑,最好是语义上的的规定。C++用变量必须显示的声明解决了这个问题,但Python没有额外的变量声明语法,如果仅仅是出于上面所说的目的引入类似C++的变量必须显式的声明就显得太得不偿失了。
所以,self.var这种语法就是一个非常优美的解决方案。我们在函数里写上self.var这种语法,解释器就不用费力地在全局范围内进行变量的查找。换句话说,局部变量和成员变量存在于两个不同的命名空间,我们需要告诉Python我们用的是哪个空间。
Python学习群:238757010
为什么Python类成员的调用和声明必须有"this"?的更多相关文章
- python 类成员函数
http://cowboy.1988.blog.163.com/blog/static/75105798201091141521583/ 这篇文章总结的非常好 主要注意的地方是 1,在类内调用成员函数 ...
- 转:从pickle看python类成员的动态加载和类的定位
pickle是Python轻便的对象序列化工具.使用pickle可以方便地把python对象写入文件对象中,或者像soap那样在socket间传送. 按照python的一贯作风,类的成员在 ...
- 测试Python类成员的单下划线,双下划线,两头下划线的区别
首先原谅一个菜鸟叫他“两头下划线”.记得在windows编程中,很多宏定义使用下划线+大写,给人逼格很高的错觉.对于Python下划线的认识,大概是从__dict__这个属性开始的,看__dict__ ...
- python - 类成员修饰符
在java,c#类的成员修饰符包括,公有.私有.程序集可用的.受保护的. 对于python来说,只有两个成员修饰符:公有成员,私有成员 成员修饰符是来修饰谁呢?当然是修饰成员了.那么python类的成 ...
- python 类成员知识点学习的一个坑(初学者,大神请绕行)
先来段小程序class Foo: name = "abc" def __init__(self,age): self.age = age print(Foo.name)Foo.na ...
- python 类成员的修饰符
类的所有成员在上一步骤中已经做了详细的介绍,对于每一个类的成员而言都有两种形式: 公有成员,在任何地方都能访问 私有成员,只有在类的内部才能方法 私有成员和公有成员的定义不同:私有成员命名时,前两个字 ...
- Python类和实例调用
self指向的是实例对象,作为第一个参数,使用时不需要传入此参数. class Student(object): #定义一个Student类, def __init__(self, name, sco ...
- python 面向对象和类成员和异常处理
python 面向对象 你把自己想象成一个上帝,你要创造一个星球,首先你要把它揉成一个个球,两个直径就能创造一个球 class star: '''名字(name),赤道直径(equatorial di ...
- C#的类成员初始化顺序
C#的类成员的定义和声明如下 using UnityEngine; using System.Collections; public class TestController : ECControll ...
随机推荐
- Linux 系统的网络基础_【all】
网络基础 1.网线:568B: 白橙 橙色 白绿 蓝色 白蓝 绿色 白棕 棕色 2.交换机:电信号转发的网络设备,它可以为接入交换机的任2个网络节点设备提供电信号通信 3.路由器:连接局域网,广域网的 ...
- Linux系统安全最小原则
系统安全最小原则 1.安装Linux系统最小化,选包最小化,不用就不安装2.开机服务最小化(5个)ssh network sysstat crontd rsyslog3.操作命令最小化 rm -rf ...
- 3星|《结构思考力》:用金字塔原理整理PPT的思路,案例偏简单
结构思考力 名义上全书是讲结构化思考,实际内容是用结构化思考的方法来整理PPT的思路,让PPT的逻辑更清晰.少部分提到如何修改标题更吸引人,如何做图表设计. 书中结构化思考的基本思路,重要的有两个:1 ...
- DevExpress01、独立使用的控件
XtraEditors 库提供了只能独立使用的控件,也就是说不能在容器控件的内置编辑中使用它们. 这些控件包括: 几种类型的列表框.数据导航控件.滚动条和一个按钮控件. 这些控件都是 BaseStyl ...
- JNLP应用程序无法打开的解决办法
JNLP应用程序无法打开: 1.控制面板-Java-Java 选项卡-查看.用户选项卡勾选对应版本JDK(没有就添加,路径填类似:D:\Program Files\Java\jre6\bin\java ...
- 经验总结13--EF配置
EF配置,开发前的准备及步骤. 使用V22013和EF6.1. 1.使用VS新建MVC项目. 2.创建实体类. 3.配置web.config的数据库链接字符串. <connectionStrin ...
- [luogu3941] 入阵曲
题面 话说题目前面的那首诗还挺有意境的啊哈哈. 可能今天要把中文的标点都换成英文的了, 先熟悉一下吧... 好了, 进入正题, 求一个矩阵内有多少个子矩阵满足这个子矩阵的和模k为零.看到矩 ...
- nodejs实现mysql数据库的简单例子
在MySQLWorkbench中创建table存储用户的tokenId信息: use token; SET FOREIGN_KEY_CHECKS = ; DROP TABLE IF EXISTS `a ...
- PATtest1.3:最大子列和
题目源于:https://pintia.cn/problem-sets/16/problems/663 题目要求:输入一个数列,求其最大子列和. 问题反馈:1.部分C++代码不是很熟练 2.没有仔细读 ...
- day 88 Vue学习之八geetest滑动验证
本节目录 一 geetest前端web中使用 二 xxx 三 xxx 四 xxx 五 xxx 六 xxx 七 xxx 八 xxx 一 geetest前端web中使用 下载gt文件,官网地址,下面我 ...