python 参数列表中的self 显式不等于冗余


Posted in Python onDecember 01, 2008

self在区分全局变量/函数和对象中的成员变量/函数十分有用。例如,它提供了一种作用域机制,我个人认为比Ruby的@和@@清晰多了,这可能是习惯使然吧,但它确实和C++、Java中的this很相似。
然而,self总是有令我困扰的地方,我以前在这里说过—我曾幻想能在Python3中这些能得以改进,然后通常会引发一轮热议并最终以人们所说的“显胜于隐”告终。
我在巴西的时候曾和Luciano Ramalho(巴西Python组织的主席)有过一次交谈。他让我明白并非无处不在的self让我困扰不已,而是参数列表中的self,我想也称为非pythonic(un-pythonic)。
它是如何使用的
下面是一些简单的Python代码,说明了如何使用类。

def f(): pass 
a = 1 
class C1(object): 
a = 2 
def m1(self): 
print a # Prints '1' 
print self.a # Prints '2' 
f() # The global version 
self.m2() # Must scope other members 
def m2(self): pass 
obj = C1() 
obj.m1()

首先看f()和a,它们都可在全局作用域中调用。类C1被定义成继承自object,这是定义一个新类的标准过程(我想在Python3中这些会变得更加不明显)。
注意,m1()和m2()的第一个参数都是self。在Python中,self不是关键字。但按照惯例“self”代表当前对象的地址,也就是对象的地址通常是第一个参数。
在类范围上定义a是创建对象作用域的方式之一。你也可以在a的method里赋值给self.a,并且第一次运行该语句时就分配了这个域的内存空间。但有必要区分两种版本的a。若在method内部使用a,那么这个a就是全局版本的,而self.a体现的是对象域(你也可以在类内部对全局变量进行赋值,这里我暂不考虑这种情况)。
同样地,一个对f()的非限定调用(unqualified call)造就了全局函数,通过对其限定self.m2()调用的是成员函数(同时将当前对象地址作为传递给m2()的self变量)。
现在来看一个含有带参数的method的类:
class C2(object): 
def m2(self, a, b): pass

为了调用该method,我们创建了一个对象实例,然后使用点表达式调用对象obj上的m2():
obj = C2() 
obj.m2(1,2)

在调用过程中,obj的地址作为self变量在m2()中隐含传递,这里遇到了一个严重的矛盾:为何当定义method时隐式好于显式,而调用method时隐式也毫无问题?
当然我想这可能是method调用语法所要求的,但这就意味着method的定义和调用有很大不同,这里既没有“显式”也不pythonic。在调用参数个数错误的method时就能看出来:
obj.m2(1)
结果错误提示为:
Traceback (most recent call last):
File "classes.py", line 9, in <module>
obj.m2(1)
TypeError: m2() takes exactly 3 arguments (2 given)
由于method调用期间self的隐式参数传递,上述错误信息实际是说应该这样调用method:
C2.m2(obj,1,2)
即使上面这行语句运行成功,它当然也不是实际的调用方式。你应该使用常规的method调用语法,即传递两个参数:
obj.m2(1,2)
错误信息“m2() takes exactly 3 arguments (2 given)”不仅让初学者十分糊涂,我每次看到它后也常常懵住。我想这既表明了它是非Pythonic、也直指method定义和调用的矛盾。
绝望的建议
尽管漫长历史中尽是绝望,我又有哪些建议呢?
在Python3.1中增加self为关键字(有一点更加向后不兼容)(或直接使用this来使C++和Java程序员时更容易过渡)。而所有与self有关的已有规则都不变。
唯一的改变是:你不必将self放入method参数列表中。这是唯一隐式的地方,其它都是显式的—除了依旧不变的method调用。
它实现了method定义和调用的一致性。你可以定义一个与调用时具有相同参数个数的method。当调用method所传递参数个数出错时,错误信息会通知method应含有的实际参数个数,而不是多出一个。
显式 vs.冗余
在我再一次听到“显胜于隐”之前,让某件事变得清晰和变得冗余还是有区别的。我们已有这样一种语言:它让你历经了无数考验,原因就是起初看起来似乎很好但之后问题却越来越多。它叫做Java。
如果想让每一件东西都变为显式,我们可以使用C或汇编以及其它能够精确说明和展现机器内部运行细节的语言。
强制程序员将self放入method参数列表与显式根本不沾边,它只是强制造成冗余的做法,也不会增加编程的表达方式(已经知道是一个method了,何必还要在参数列表中加入self来提醒我们呢)。我认为,它是死板的,也是非pythonic。
Python 相关文章推荐
python计算对角线有理函数插值的方法
May 07 Python
Python利用flask sqlalchemy实现分页效果
Aug 02 Python
Python实现感知器模型、两层神经网络
Dec 19 Python
python实现银联支付和支付宝支付接入
May 07 Python
python自定义时钟类、定时任务类
Feb 22 Python
python3.7实现云之讯、聚合短信平台的短信发送功能
Sep 26 Python
pycharm的python_stubs问题
Apr 08 Python
Pycharm pyuic5实现将ui文件转为py文件,让UI界面成功显示
Apr 08 Python
pycharm中使用request和Pytest进行接口测试的方法
Jul 31 Python
Python用K-means聚类算法进行客户分群的实现
Aug 23 Python
了解一下python内建模块collections
Sep 07 Python
在 Python 中使用 7zip 备份文件的操作
Dec 11 Python
Python GAE、Django导出Excel的方法
Nov 24 #Python
Python类的基础入门知识
Nov 24 #Python
Python 连连看连接算法
Nov 22 #Python
python sqlobject(mysql)中文乱码解决方法
Nov 14 #Python
Python转码问题的解决方法
Oct 07 #Python
Python函数学习笔记
Oct 07 #Python
Python日期操作学习笔记
Oct 07 #Python
You might like
MySQL修改密码方法总结
2008/03/25 PHP
php HtmlReplace输入过滤安全函数
2010/07/03 PHP
php图片加中文水印实现代码分享
2012/10/31 PHP
PHP执行linux命令常用函数汇总
2016/02/02 PHP
CentOS7.0下安装PHP5.6.30服务的教程详解
2018/09/29 PHP
发布一个高效的JavaScript分析、压缩工具 JavaScript Analyser
2007/11/30 Javascript
JavaScript中的异常捕捉介绍
2014/12/31 Javascript
jQuery+json实现的简易Ajax调用实例
2015/12/14 Javascript
jQuery 特性操作详解及实例代码
2016/09/29 Javascript
EditPlus中的正则表达式 实战(2)
2016/12/15 Javascript
canvas实现动态小球重叠效果
2017/02/06 Javascript
详解webpack3编译兼容IE8的正确姿势
2017/12/21 Javascript
vue中的provide/inject的学习使用
2018/05/09 Javascript
jquery ajaxfileuplod 上传文件 essyui laoding 效果【防止重复上传文件】
2018/05/26 jQuery
浅谈Vue.js 关于页面加载完成后执行一个方法的问题
2019/04/01 Javascript
Vue 页面权限控制和登陆验证功能的实例代码
2019/06/20 Javascript
element-ui中Table表格省市区合并单元格的方法实现
2019/08/07 Javascript
通过扫小程序码实现网站登陆功能
2019/08/22 Javascript
taro小程序添加骨架屏的实现代码
2019/11/15 Javascript
vue.js实现简单购物车功能
2020/05/30 Javascript
Vue Router中应用中间件的方法
2020/08/06 Javascript
windows如何把已安装的nodejs高版本降级为低版本(图文教程)
2020/12/14 NodeJs
[01:07:02]DOTA2-DPC中国联赛 正赛 iG vs PSG.LGD BO3 第三场 2月26日
2021/03/11 DOTA
python实现植物大战僵尸游戏实例代码
2019/06/10 Python
浅谈tensorflow之内存暴涨问题
2020/02/05 Python
Python列表嵌套常见坑点及解决方案
2020/09/30 Python
css3 中的新特性加强记忆详解
2016/04/16 HTML / CSS
娇韵诗Clarins意大利官方网站:法国天然护肤品牌
2020/03/11 全球购物
struct和class的区别
2015/11/20 面试题
如何写出高质量、高性能的MySQL查询
2014/11/17 面试题
介绍一下Ruby的特点
2013/01/20 面试题
劳资员岗位职责
2013/11/11 职场文书
医院办公室主任职责
2013/12/29 职场文书
2014年学校领导班子对照检查材料
2014/09/19 职场文书
北京故宫的导游词
2015/01/31 职场文书
优秀共产党员事迹材料2016
2016/02/29 职场文书