虽然我现在写过一些Python代码,但实际上几乎还没用过Class,而且一直觉得一个很别扭的事情是,Class中的函数都要写个参数self,虽然实例化调用的时候不需要。

当然,一开始就知道Python这样设计应该有它的理由,具体是什么也没去考虑。

今天看到一个这样的说法:

源地址:http://www.douban.com/group/topic/19376685/

我解释一下python的类方法为什么要写一个self参数

来自: 巴特富莱韦杭普(Butterfly Wet-hamp) 2011-04-26 23:18:19

这是对前面一个php程序员问python方法为什么要手写一个self的回答,当时那个帖非常的热闹,但是下面没有一个回复讲到要点,等我有空,已经找不到原帖了。

原因有多重。首先是python中几乎所有的东西的一级对象(一级对象的定义:http://en.wikipedia.org/wiki/First-class_object),method也不例外,比如你写一个: 
class X: 
 def f(self, a, b): 
  ... 
那么可以这样引用f: 
X.__dict__['f'] 
或者 
X.f.__func__

现在问题来了,得到f以后怎么调用?f是一个方法,方法必须作用于对象。如果x是一个X对象,我们可以x.f(...),但是如果是以上面的方式得到的f呢?怎么f让作用于某个对象?最直观的方法就是和参数一起传递进去。

当然的限不同的设计也可以满足上面制。比如不要手写的self参数,增加this关键字,增加一个调用f个格式。这样的设计和pep20第二条不符合。

为理解python的self,不妨对比一下ruby和javascript。ruby的方式是方法不是一级对象,所以绕过了这个问题。javascript没有类,方法在调用时this会绑定到方法所属的对象,函数调用时this绑定到window,函数做构造器调用时this绑定到新对象。这么多规则,比Python复杂。

 
11人 喜欢 喜欢
  • 狼.敬畏生命 (wolf python london) 2011-04-27 08:38:50

    说下我的理解:

    我在学习python的时候,也发现一直写着self很别扭,在c++中,this指针是隐式的,除非不得以的时候,,比如传进来的参数和类的成员变量的名字相同,或者要返回当前对象。 而python的self是显示的。而且this指针基本上不用在函数头里面。

    python是动态语言,设计出来的类和静态语言的格式不同,首先c++在类的定义(声明)时,会指定类的成员变量,比如在private:里。但是Python不行,它没法显式的说 哪个属性是自己的,而且属性还可以动态的增加,此时,一个解决方案出来了,增加self,通过self.访问的就可以做为类的属性。至于类的方法为什么要显式的写上self(我感觉,完全可以由解释器隐式添加上去),估计就是python的哲学导致的:Explicit is better than implicit.

  • zizi (努力赚钱中) 2011-04-27 09:20:05

    个人理解: 
    除了前两种形式外还有第三种形式X.f,这个返回的和前两个不同。 
    其实你写不写self或者其他什么对于python来说都无所谓,对于python来说,方法就分两种一种是绑定的,一种是不绑定。对于绑定的方法来说,python就会把他绑定的对象作为第一个参数传给这个对象。self仅仅是提醒你这个方法会被绑定到实例上而已。

    同时这样做还有个好处就是兼容python的C/API部分。Python本身是用C写成的,在C中实现类似面向机制都是这么写的: 
    SSL_connect(SSL *ssl, ARG *arg1) 
    再看看Python C API的OO部分 
    int PyObject_Print(PyObject *o, FILE *fp, int flags)

    所以我大胆猜测self的机制是从C继承而来的。

  • zizi (努力赚钱中) 2011-04-27 09:26:38

    PS:对于你说ruby中方法不是第一级对象这个事情能否解释一下? 
    我RUBY用的不多,但是我印象中ruby的方法应该能满足first class的定义。

  • 李保银 2011-04-27 10:21:11

    self是类方法的一个位置参数,它就是类的实例对象自己,当实例调用方法时: 
    instance = X() 
    instance.f('a', 'b') 
    等同于: 
    X.f(instance, 'a', 'b') 
    第一个参数是实例自己。

  •  

    bachue 2013-05-16 15:58:28

    "当然的限不同的设计也可以满足上面制。比如不要手写的self参数,增加this关键字,增加一个调用f个格式。这样的设计和pep20第二条不符合。" 
    不能苟同 如果真的是“Explicit is better than implicit.”,为何x.f()中的x是以implicit的方法送进f的?为何不写成f(x)?为何Python不去除面向对象以完全实现“Explicit is better than implicit.”?

  • alinwawa 2013-09-08 05:25:57

    狼.敬畏生命,写得最好。确实python牺牲了隐式的简洁,但是换来了极大的灵活性,比如随意添加对象属性。这个比c++方便太多倍了。

  • 苏打 2013-09-08 08:59:36

    说下我的理解: 我在学习python的时候,也发现一直写着self很别扭,在c++中,this指针是隐式 ...狼.敬畏生命

    靠IDE能否省掉这些重复?

  • 精密空调 2013-09-11 12:01:24

    习惯上,方法的第一个参数命名为 self。这仅仅是一个约定:对Python而言,self 绝对没有任何特殊含义。(然而要注意的是,如果不遵守这个约定,别的Python程序员阅读你的代码时会有不便,而且有些类浏览程序也是遵循此约定开发的。)

虽然基本上算是理解了Python为什么要加这个self。但是!!!我必须想明白这个但是!!!我之所以喜欢Python,就是因为它的简洁,我之前的理解是:

用最少的工作做最多的事情

繁琐的工作没必要做

出来的结果跟想象的结果惊人的一致

正因为这样,所以,我实在是无法理解这个self,无论从哪方面考虑,它都是多余的,既然连{}这种东西都能省,为什么一个self不能省?!纵使PEP 20哲学说清晰好过模糊,但为什么还支持带缺省值的参数,为什么不像C语言那样不能省略?

所以,无论是从Python设计哲学还是设计技术细节来考虑,这个self真的是一个很奇怪的东西,再怎么说,前面已经有个class了,这一段就是类啊!!!

关于Python中的self的更多相关文章

  1. [转]Python中的str与unicode处理方法

    早上被python的编码搞得抓耳挠腮,在搜资料的时候感觉这篇博文很不错,所以收藏在此. python2.x中处理中文,是一件头疼的事情.网上写这方面的文章,测次不齐,而且都会有点错误,所以在这里打算自 ...

  2. python中的Ellipsis

    ...在python中居然是个常量 print(...) # Ellipsis 看别人怎么装逼 https://www.keakon.net/2014/12/05/Python%E8%A3%85%E9 ...

  3. python中的默认参数

    https://eastlakeside.gitbooks.io/interpy-zh/content/Mutation/ 看下面的代码 def add_to(num, target=[]): tar ...

  4. Python中的类、对象、继承

    类 Python中,类的命名使用帕斯卡命名方式,即首字母大写. Python中定义类的方式如下: class 类名([父类名[,父类名[,...]]]): pass 省略父类名表示该类直接继承自obj ...

  5. python中的TypeError错误解决办法

    新手在学习python时候,会遇到很多的坑,下面来具体说说其中一个. 在使用python编写面向对象的程序时,新手可能遇到TypeError: this constructor takes no ar ...

  6. python中的迭代、生成器等等

    本人对编程语言实在是一窍不通啊...今天看了廖雪峰老师的关于迭代,迭代器,生成器,递归等等,word天,这都什么跟什么啊... 1.关于迭代 如果给定一个list或tuple,我们可以通过for循环来 ...

  7. python2.7高级编程 笔记二(Python中的描述符)

    Python中包含了许多内建的语言特性,它们使得代码简洁且易于理解.这些特性包括列表/集合/字典推导式,属性(property).以及装饰器(decorator).对于大部分特性来说,这些" ...

  8. python cookbook 学习系列(一) python中的装饰器

    简介 装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象.它经常用于有切面需求的场景,比如:插入日志.性能测试.事务处理.缓 ...

  9. 用 ElementTree 在 Python 中解析 XML

    用 ElementTree 在 Python 中解析 XML 原文: http://eli.thegreenplace.net/2012/03/15/processing-xml-in-python- ...

  10. Python中操作mysql的pymysql模块详解

    Python中操作mysql的pymysql模块详解 前言 pymsql是Python中操作MySQL的模块,其使用方法和MySQLdb几乎相同.但目前pymysql支持python3.x而后者不支持 ...

随机推荐

  1. 【Java集合框架】规则集--Set

    集合: Java主要支持三种: 1.规则集(Set) 用于存储一组不重复的元素 2.线性表(List) 用于存储一个由元素构成的有序集合 3.队列(Queue) 同与数据结构中的队列,存储用先进先出的 ...

  2. date.plugin.js 日期插件

    //定义命名空间 var DatePlugin; if (!DatePlugin) DatePlugin = {}; /*整理时间:2015-05-28*/ var defaultFormat = & ...

  3. Ejabberd源码解析前奏--管理

    一.ejabberdctl 使用ejabberdctl命令行管理脚本,你可以执行ejabberdctl命令和一些普通的ejabberd命令(后面会详细解说).这意味着你可以在一个本地或远程ejabbe ...

  4. java web 学习二(Tomcat服务器学习和使用1)

    一.Tomcat服务器端口的配置 Tomcat的所有配置都放在conf文件夹之中,里面的server.xml文件是配置的核心文件. 如果想修改Tomcat服务器的启动端口,则可以在server.xml ...

  5. 基于Fragment实现Tab的切换,滑出侧边栏

    最近在学习Fragment(碎片)这是android3.0以后提出的概念,很多pad上面的设置部分都是通过Fragment来实现的,先看看具体的效果吧(图一)  (图二) (图三)第一章图片是初始时的 ...

  6. delphi7 开发布局

    delphi7界面布局(就是各种框框,代码管理器之类的东东)好了的,为什么以打开个新项目或者下次进入开发界面是环境的布局全部变了,如何才能锁定窗口布局? 在菜单栏最右边,有一个按钮save curre ...

  7. The Administration Console(管理员控制台)

    当你的应用准备好了首次露面时,你要创建一个管理员用户以及将这个应用安装到App Engine上.你使用你的管理员帐户创建和管理这个应用,查看它的资源利用统计,消息日志以及更多.所有这些基于一个叫做管理 ...

  8. 给sublime text添加ubuntu launcher快捷方式

    1.下载sublime text 2文件,解压并复制到/opt目录,文件夹名称不要含有空格 2.在/usr/share/applications目录下新建sublime_text.desktop文件 ...

  9. delphi回调函数

    文章来源: http://anony3721.blog.163.com/blog/static/5119742010866050589/ 一.主单元 unit UnMain; interface us ...

  10. ocp 1Z0-051 141-175题解析

    141. View the Exhibitand examine the structure of CUSTOMERS and GRADES tables. You need to displayna ...