刚开始学习Python的类写法的时候觉得很是麻烦,为什么定义时需要而调用时又不需要,为什么不能内部简化从而减少我们敲击键盘的次数?你看完这篇文章后就会明白所有的疑问。

self代表类的实例,而非类。

实例来说明

Python

classTest:defprt(self):print(self)print(self.__class__)

t=Test()

t.prt()

执行结果如下

Python

<__main__.Test object at 0x000000000284E080>

从上面的例子中可以很明显的看出,self代表的是类的实例。而self.class则指向类。

self不必非写成self

有很多童鞋是先学习别的语言然后学习Python的,所以总觉得self怪怪的,想写成this,可以吗?

当然可以,还是把上面的代码改写一下。

Python

classTest:defprt(this):print(this)print(this.__class__)

t=Test()

t.prt()

改成this后,运行结果完全一样。

当然,最好还是尊重约定俗成的习惯,使用self。

self可以不写吗

在Python的解释器内部,当我们调用t.prt()时,实际上Python解释成Test.prt(t),也就是说把self替换成类的实例。

有兴趣的童鞋可以把上面的t.prt()一行改写一下,运行后的实际结果完全相同。

实际上已经部分说明了self在定义时不可以省略,如果非要试一下,那么请看下面:

Python

classTest:defprt():print(self)

t=Test()

t.prt()

运行时提醒错误如下:prt在定义时没有参数,但是我们运行时强行传了一个参数。

由于上面解释过了t.prt()等同于Test.prt(t),所以程序提醒我们多传了一个参数t。

Python

Traceback (most recent call last):

File"h.py", line 6, in t.prt()

TypeError: prt() takes 0 positional arguments but1 was given

当然,如果我们的定义和调用时均不传类实例是可以的,这就是类方法。

Python

classTest:defprt():print(__class__)

Test.prt()

运行结果如下

Python

在继承时,传入的是哪个实例,就是那个传入的实例,而不是指定义了self的类的实例。

先看代码

Python

classParent:defpprt(self):print(self)classChild(Parent):defcprt(self):print(self)

c=Child()

c.cprt()

c.pprt()

p=Parent()

p.pprt()

运行结果如下

Python

<__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指的是描述符类的实例

不太容易理解,先看实例:

Python

classDesc:def __get__(self, ins, cls):print('self in Desc: %s' %self )print(self, ins, cls)classTest:

x=Desc()defprt(self):print('self in Test: %s' %self)

t=Test()

t.prt()

t.x

运行结果如下:

Python

self in Test: <__main__.Test object at 0x0000000002A570B8>selfin Desc: <__main__.Desc object at 0x000000000283E208>

<__main__.Desc object at 0x000000000283E208> <__main__.Test object at 0x0000000002A570B8>

大部分童鞋开始有疑问了,为什么在Desc类中定义的self不是应该是调用它的实例t吗?怎么变成了Desc类的实例了呢?

注意:此处需要睁大眼睛看清楚了,这里调用的是t.x,也就是说是Test类的实例t的属性x,由于实例t中并没有定义属性x,所以找到了类属性x,而该属性是描述符属性,为Desc类的实例而已,所以此处并没有顶用Test的任何方法。

那么我们如果直接通过类来调用属性x也可以得到相同的结果。

下面是把t.x改为Test.x运行的结果。

Python

self in Test: <__main__.Test object at 0x00000000022570B8>selfin Desc: <__main__.Desc object at 0x000000000223E208>

<__main__.Desc object at 0x000000000223E208> None

题外话:由于在很多时候描述符类中仍然需要知道调用该描述符的实例是谁,所以在描述符类中存在第二个参数ins,用来表示调用它的类实例,所以t.x时可以看到第三行中的运行结果中第二项为。而采用Test.x进行调用时,由于没有实例,所以返回None。

总结

self在定义时需要定义,但是在调用时会自动传入。

self的名字并不是规定死的,但是最好还是按照约定是用self

self总是指调用时的类的实例。

python中home定义是什么_搞清楚Python中self的含义相关推荐

  1. python怎么创建txt文件啊_搞定Python项目依赖:requirements.txt文件的创建和使用

    Python的强大在于它拥有数量众多的第三方库协助开发,在编写Python项目时,我们经常会使用很多第三方模块.由于不同设备和系统的差异性,导致我们很难分散地控制项目依赖(头铁的同学请绕道),于是re ...

  2. python中home定义是什么_第48p,什么是函数?,Python中函数的定义

    原标题:第48p,什么是函数?,Python中函数的定义 大家好,我是 杨数 Tos ,这是<从 零 基础到大神>系列课程的第 48 篇文章 ,第三阶段的课程 : Python进阶知识:详 ...

  3. python类方法需要传入cls参数_如何从Python 3.x中的类定义传递参数到元类?

    这是如何从类定义向元类传递参数的python 3.x版本?问题,根据请求单独列出,因为答案与python 2.x明显不同. 在python 3.x中,如何将参数传递给元类的__prepare__.__ ...

  4. python函数中可变参数的传递方式_详解Python函数可变参数定义及其参数传递方式...

    Python函数可变参数定义及其参数传递方式详解 python中 函数不定参数的定义形式如下 1. func(*args) 传入的参数为以元组形式存在args中,如: def func(*args): ...

  5. python采用面向对象编程模式吗_如何理解 Python 中的面向对象编程?

    现如今面向对象编程的使用非常广泛,本文我们就来探讨一下Python中的面向对象编程. 作者 | Radek Fabisiak 译者 | 弯月,责编 | 郭芮 以下为译文: Python支持多种类型的编 ...

  6. python中的符号下划线_详解Python中下划线的使用方法

    编程派微信号:codingpy 这篇文章讨论Python中下划线_的使用.跟Python中很多用法类似,下划线 _ 的不同用法绝大部分(不全是)都是一种惯例约定. 单个下划线(_) 主要有三种情况: ...

  7. python中var是什么变量_一、 Python概述、变量

    一.        Python概述 1.python是一门面向对象,解释型的脚本语言.语法简洁,编写效率高,但是执行(底层运行)效率低(总的来说解释语言执行效率低于编译语言). 注意:本博客所有的代 ...

  8. python中什么是可变参数_详解Python的三种可变参数

    详解Python的三种可变参数 可变参数 可变参数应该最简单,在C/C++和Java等语言中都有,就是用*号来表示,例如 def testArg(*arg) 你可以传入任意多个元素(包括0)到参数中, ...

  9. python游戏中调整箭头下落速度_入门 | 三行Python代码,让数据预处理速度提高2到6倍...

    原标题:入门 | 三行Python代码,让数据预处理速度提高2到6倍 选自TowardsDataScience 作者:George Seif,机器之心编译 在 Python 中,我们可以找到原生的并行 ...

  10. java如何给一个链表定义和传值_如何在CUDA中为Transformer编写一个PyTorch自定义层...

    如今,深度学习模型处于持续的演进中,它们正变得庞大而复杂.研究者们通常通过组合现有的 TensorFlow 或 PyTorch 操作符来发现新的架构.然而,有时候,我们可能需要通过自定义的操作符来实现 ...

最新文章

  1. 内存条结构_CPU是电脑里最难坏的硬件,为什么不敢终身质保,而内存条却可以...
  2. 新中大oracle实列名,新中大财务软件操作流程(完整版)
  3. 2015-10-15 css3
  4. linux ll 文件大小单位_该如何改善 Linux 系统性能?
  5. BlackBerry 应用程序开发者指南 第二卷:高级--第11章 管理通知(Notification)
  6. 栈和队列:2.队列(Queue)及其C语言实现
  7. 运行 lighttrack 遇到错误和解决方法
  8. @程序员,你的编程方式已过时,云开发时代来临!
  9. dubbo源码之SPI机制源码
  10. 【蓝桥杯国赛真题24】Scratch货物运输 第十三届蓝桥杯 图形化编程scratch国赛真题和答案讲解
  11. SpringBoot-DDD领域驱动设计的概念
  12. 对称加密算法原理简介
  13. CentOS 6.3安装 flash控件成功案例(其它方法未成功)
  14. Linux下rsync安装与配置
  15. 火爆科研圈的三维重建技术:Neural radiance fields (NeRF)
  16. 【UV打印机】电气之光电传感器
  17. Hystrix断路器执行原理
  18. python官网各个版本下载地址
  19. Chrome浏览器首页被hao123劫持的解决办法
  20. 战痘实录,又同样烦恼的可以看看(转)

热门文章

  1. MySQL指令集集合
  2. 《云计算:原理与范式》一3.2 知识经济时代的来临
  3. (转)战斗bug技巧全攻略
  4. IC卡读写器VB.NET源代码
  5. 用思科2610搭建PSTN拨号网络
  6. java net 安卓_Java和Android Http连接程序:使用java.net.URL 下载服务器图片到客户端...
  7. 以rpm包形式升级Linux驱动
  8. linux下实现在程序运行时的函数替换(热补丁)
  9. Ceph 撸源码系列(二):Ceph源代码里的那些锁 std::mutex(2 of 3)
  10. SFML图形库学习:环境部署