self是什么东西
python的self就相当于C++的this指针!
类就是图纸,而由类实例化后的对象就是能够住人的房子!
而self就相当于自己房子的门牌号码
以下为看到别人的笔记介绍的比较清楚,可以参考以下

#
刚开始学习Python的类写法的时候觉得很是麻烦,为什么定义时需要而调用时又不需要,为什么不能内部简化从而减少我们敲击键盘的次数?你看完这篇文章后就会明白所有的疑问。self代表类的实例,而非类。实例来说明:class Test:def prt(self):print(self)print(self.__class__)t = Test()
t.prt()执行结果如下
<__main__.Test object at 0x000000000284E080>
<class '__main__.Test'>从上面的例子中可以很明显的看出,self代表的是类的实例。而self.class则指向类。self不必非写成self有很多童鞋是先学习别的语言然后学习Python的,所以总觉得self怪怪的,想写成this,可以吗?当然可以,还是把上面的代码改写一下。class Test:def prt(this):print(this)print(this.__class__)t = Test()
t.prt()改成this后,运行结果完全一样。当然,最好还是尊重约定俗成的习惯,使用self。self可以不写吗在Python的解释器内部,当我们调用t.prt()时,实际上Python解释成Test.prt(t),也就是说把self替换成类的实例。有兴趣的童鞋可以把上面的t.prt()一行改写一下,运行后的实际结果完全相同。实际上已经部分说明了self在定义时不可以省略,如果非要试一下,那么请看下class Test:def prt():print(self)t = Test()
t.prt()运行时提醒错误如下:prt在定义时没有参数,但是我们运行时强行传了一个参数。由于上面解释过了t.prt()等同于Test.prt(t),所以程序提醒我们多传了一个参数t。Traceback (most recent call last):File "h.py", line 6, in <module>t.prt()
TypeError: prt() takes 0 positional arguments but 1 was given当然,如果我们的定义和调用时均不传类实例是可以的,这就是类方法。class Test:def prt():print(__class__)
Test.prt()运行结果如下
?
1<class '__main__.Test'>在继承时,传入的是哪个实例,就是那个传入的实例,而不是指定义了self的类的实例。先看代码class Parent:def pprt(self):print(self)class Child(Parent):def cprt(self):print(self)
c = Child()
c.cprt()
c.pprt()
p = Parent()
p.pprt()运行结果如下<__main__.Child object at 0x0000000002A47080>
<__main__.Child object at 0x0000000002A47080>
<__main__.Parent object at 0x0000000002A47240>解释:运行c.cprt()时应该没有理解问题,指的是Child类的实例。但是在运行c.pprt()时,等同于Child.pprt(c),所以self指的依然是Child类的实例,由于self中没有定义pprt()方法,所以沿着继承树往上找,发现在父类Parent中定义了pprt()方法,所以就会成功调用。在描述符类中,self指的是描述符类的实例不太容易理解,先看实例class Desc:def __get__(self, ins, cls):print('self in Desc: %s ' % self )print(self, ins, cls)
class Test:x = Desc()def prt(self):print('self in Test: %s' % self)
t = Test()
t.prt()
t.x运行结果如下:
?
1
2
3self in Test: <__main__.Test object at 0x0000000002A570B8>
self in Desc: <__main__.Desc object at 0x000000000283E208>
<__main__.Desc object at 0x000000000283E208> <__main__.Test object at 0x0000000002A570B8> <class '__main__.Test'>大部分童鞋开始有疑问了,为什么在Desc类中定义的self不是应该是调用它的实例t吗?怎么变成了Desc类的实例了呢?注意:此处需要睁大眼睛看清楚了,这里调用的是t.x,也就是说是Test类的实例t的属性x,由于实例t中并没有定义属性x,所以找到了类属性x,而该属性是描述符属性,为Desc类的实例而已,所以此处并没有顶用Test的任何方法。那么我们如果直接通过类来调用属性x也可以得到相同的结果。下面是把t.x改为Test.x运行的结果。
self in Test: <__main__.Test object at 0x00000000022570B8>
self in Desc: <__main__.Desc object at 0x000000000223E208>
<__main__.Desc object at 0x000000000223E208> None <class '__main__.Test'>题外话:由于在很多时候描述符类中仍然需要知道调用该描述符的实例是谁,所以在描述符类中存在第二个参数ins,用来表示调用它的类实例,所以t.x时可以看到第三行中的运行结果中第二项为<main.Test object at 0x0000000002A570B8>。而采用Test.x进行调用时,由于没有实例,所以返回None。从OO的本质理解python中的self
举个栗子,假设我要对用户的数据进行操作,用户的数据包含name和age。如果用面向过程的话,实现出来是下面这样子的。def user_init(user,name,age): user['name'] = name user['age'] = age def set_user_name(user, x): user['name'] = x def set_user_age(user, x): user['age'] = x def get_user_name(user): return user['name'] def get_user_age(user): return user['age'] myself = {}
user_init(myself,'kzc',17)
print get_user_age(myself)
set_user_age(myself,20)
print get_user_age(myself) 可以看到,对用户的各种操作,都要传user参数进去。
如果用面向对象的话,就不用每次把user参数传来传去,把相关的数据和操作绑定在一个地方,在这个类的各个地方,可以方便的获取数据。
之所以可以在类中的各个地方访问数据,本质就是绑定了self这个东西,它方法的第一个参数,当然可以不叫self,叫其它名字,self只不过是个约定。
下面是面向对象的实现,可以看到,结构化多了,清晰可读。class User(object): def __init__(self,name,age): self.name = name self.age = age def SetName(self,name): self.name = name def SetAge(self,age): self.age = age def GetName(self): return self.name def GetAge(self): return self.age u = User('kzc',17)
print u.GetName()
print u.GetAge() 从上面这个例子可以看出,其实面向对象挺有用的,只不过大多数人抽象的不好,封装的不好,错误的运用。总结self在定义时需要定义,但是在调用时会自动传入。self的名字并不是规定死的,但是最好还是按照约定是用selfself总是指调用时的类的实例。

面向对象编程--之二相关推荐

  1. JavaScript 面向对象编程(二) —— 构造函数 / 原型 / 继承 / ES5 新增方法

    本篇为 JavaScript 进阶 ES6 系列笔记第二篇,将陆续更新后续内容.参考:JavaScript 进阶面向对象 ES6 :ECMAScript 6 入门 : Javascript 继承机制的 ...

  2. 面向对象编程(十二)——final关键字

    阅读目录 final关键字 final修饰变量 final修饰方法 final修饰类 Final && Static 总结 final关键字 Java关键字final有"这是 ...

  3. C语言面向对象编程(二):继承详解

    在  C 语言面向对象编程(一)里说到继承,这里再详细说一下. C++ 中的继承,从派生类与基类的关系来看(出于对比 C 与 C++,只说公有继承): 派生类内部可以直接使用基类的 public .p ...

  4. javascript 学习笔记之面向对象编程(二):继承多态

    ~~接上篇~~上一篇实现了类的实现以及类成员变量和方法的定义,下面我们来了解下面向对象中两个最重要的特性:继承和多态. 继承 js中同样可以实现类的继承这一面向对象特性,继承父类中的所有成员(变量和属 ...

  5. 第四章:Java_面向对象编程(二)

    目录: 面向对象的特征之二:继承性 方法的重写 关键字super 子类对象实例化的全过程 面向对象的特征之三:多态性 Object类 Junit单元测试类 包装类 1.面向对象的特征二:继承性 1.为 ...

  6. 浅谈PHP面向对象编程(二)

    和一些面向对象的语言有所不同,PHP并不是一种纯面向对象的语言,包PIP它支持面向对象的程序设计,并可以用于开发大型的商业程序.因此学好面向对象输程对PHP程序员来说也是至关重要的.本章并针对面向对象 ...

  7. Javascript面向对象编程(二):构造函数的继承

    这个系列的第一部分,主要介绍了如何"封装"数据和方法,以及如何从原型对象生成实例. 今天要介绍的是,对象之间的"继承"的五种方法. 比如,现在有一个" ...

  8. (转)Javascript面向对象编程(二):构造函数的继承

    这个系列的第一部分,主要介绍了如何"封装"数据和方法,以及如何从原型对象生成实例. 今天要介绍的是,对象之间的"继承"的五种方法. 比如,现在有一个" ...

  9. 【转】Javascript面向对象编程(二):构造函数的继承

    原文链接:http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html 总结对象之间继承的5种方 ...

  10. 7. Java面向对象编程(二)

    文章目录 1. idea使用 1.1 idea常用快捷键(自己配置过) 1.2 idea模板 / 自定义模板 1.3 idea 查看类的所有属性.方法 2. 包 2.1 包的作用 2.2 包的基本语法 ...

最新文章

  1. jQuery(一)引入
  2. 64位windows与32位windows的区别
  3. Linux支持多种平台
  4. CF1037H Security——SAM+线段树合并
  5. SpringBoot开发案例之CountDownLatch多任务并行处理
  6. 解决React Native报错:Error:Found unexpected optical bounds (red pixel)
  7. mysql索引技术_MySQL索引类型
  8. 你跟大神程序员的差距,就在这8本内功心法
  9. easyui结合java,Spring+SpringMVC+MyBatis+easyUI整合基础篇(二)牛刀小试
  10. BSTR与CString之前的转换
  11. 看过无数 Java GC 文章,这 5 个问题你也未必知道!
  12. 一封 Cloud Native 的来信……
  13. struts1和struts2的区别2
  14. Java快逸报表展现demo_快逸报表操作积累.docx
  15. IDEA+Java+SSM+Mysql+Bootstrap+Maven实现网上书城系统
  16. 计算机配件对比,基本参数 尺寸对比 接口对比
  17. 620集成显卡和mx250,轻薄本的新独显!MX250现身英伟达官网,核显3.5倍性能
  18. 北京铁路安检全面升级 四大站特警持枪巡逻
  19. saltstack 返回mysql_saltstack(返回值存储到Mysql)
  20. 2013年2月工作小结 -- 最美工作月

热门文章

  1. Python 学习记录1
  2. 基于.Net Remoting的项目总结报告
  3. SAPI(PHP常见的四种运行模式)
  4. NYOJ 665 台球碰撞
  5. MySQL如何查询两个日期之间的记录
  6. Google Analytics 跟踪代码安装后状态总是显示'未安装跟踪代码'
  7. 吴恩达 coursera AI 专项五第三课(上)总结+作业答案
  8. Pytho学习笔记:错误,测试,调试(合)
  9. CUDA学习----sp, sm, thread, block, grid, warp概念
  10. 【算法】SVM分类精度为0,结果很烂怎么办?