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模拟登录百度代码分享(获取百度贴吧等级)
Dec 27 Python
Python实现豆瓣图片下载的方法
May 25 Python
VTK与Python实现机械臂三维模型可视化详解
Dec 13 Python
python安装twisted的问题解析
Aug 21 Python
Django开发的简易留言板案例详解
Dec 04 Python
Python检查ping终端的方法
Jan 26 Python
Django全局启用登陆验证login_required的方法
Jun 02 Python
python怎么对数字进行过滤
Jul 05 Python
Python字典取键、值对的方法步骤
Sep 30 Python
Python提取PDF指定内容并生成新文件
Jun 09 Python
python机器学习创建基于规则聊天机器人过程示例详解
Nov 02 Python
Python OpenCV实现图像模板匹配详解
Apr 07 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
php minixml详解
2008/07/19 PHP
PHP数据库调用类调用实例(详细注释)
2012/07/12 PHP
分享PHP header函数使用教程
2013/09/05 PHP
PHP实现的无限分类类库定义与用法示例【基于thinkPHP】
2018/08/06 PHP
PHP实现数组和对象的相互转换操作示例
2019/03/20 PHP
Laravel5.7框架安装与使用学习笔记图文详解
2019/04/02 PHP
使用Laravel中的查询构造器实现增删改查功能
2019/09/03 PHP
Laravel框架实现抢红包功能示例
2019/10/31 PHP
thinkphp框架实现路由重定义简化url访问地址的方法分析
2020/04/04 PHP
jquery 表单取值常用代码
2009/12/22 Javascript
javascript 处理事件绑定的一些兼容写法
2009/12/24 Javascript
详谈JavaScript内存泄漏
2014/11/14 Javascript
JavaScript实现Java中StringBuffer的方法
2015/02/09 Javascript
初步认识JavaScript函数库jQuery
2015/06/18 Javascript
javascript常用正则表达式汇总
2015/07/31 Javascript
AngularJS基础 ng-focus 指令简单示例
2016/08/01 Javascript
Highcharts学习之坐标轴
2016/08/02 Javascript
vue拦截器Vue.http.interceptors.push使用详解
2017/04/22 Javascript
mui开发中获取单选按钮、复选框的值(实例讲解)
2017/07/24 Javascript
JavaScript门道之标准库
2018/05/26 Javascript
js实现for循环跳过undefined值示例
2019/07/02 Javascript
详解ES6 扩展运算符的使用与注意事项
2020/11/12 Javascript
将Django使用的数据库从MySQL迁移到PostgreSQL的教程
2015/04/11 Python
python 调用HBase的简单实例
2016/12/18 Python
Python中%r和%s的详解及区别
2017/03/16 Python
Python之自动获取公网IP的实例讲解
2017/10/01 Python
用Python生成HTML表格的方法示例
2020/03/06 Python
python对一个数向上取整的实例方法
2020/06/18 Python
COS美国官网:知名服装品牌
2019/04/08 全球购物
生产部经理岗位职责
2013/12/16 职场文书
辩论赛主持词
2014/03/18 职场文书
聘任书模板
2014/03/29 职场文书
实习生工作证明范本
2014/09/14 职场文书
2014乡镇班子个人对照检查材料思想汇报
2014/09/26 职场文书
早会开场白台词大全
2015/06/01 职场文书
A22国内电台短波广播频率表
2022/05/10 无线电