Python中的self怎么使用

在介绍python的self用法之前,先来介绍下python中的类和实例
我们知道,面向对象最重要的概念就是类(class)和实例(instance),类是抽象的模板,比如学生这个抽象的事物,可以用一个student类来表示。而实例是根据类创建出来的一个个具体的“对象”,每一个对象都从类中继承有相同的方法,但各自的数据可能不同。
1、以student类为例,在python中,定义类如下:

class Student(object):    pass

登录后复制

(Object)表示该类从哪个类继承下来的,Object类是所有类都会继承的类。

2、实例:定义好了类,就可以通过Student类创建出Student的实例,创建实例是通过类名+()实现:

student = Student()

登录后复制

3、由于类起到模板的作用,因此,可以在创建实例的时候,把我们认为必须绑定的属性强制填写进去。这里就用到Python当中的一个内置方法__init__方法,例如在Student类时,把name、score等属性绑上去:

class Student(object):    def __init__(self, name, score):        self.name = name        self.score = score

登录后复制

这里注意:(1)、__init__方法的第一参数永远是self,表示创建的类实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。(2)、有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器会自己把实例变量传进去:

立即学习“Python免费学习笔记(深入)”;

>>>student = Student("Hugh", 99)>>>student.name"Hugh">>>student.score99

登录后复制

另外,这里self就是指类本身,self.name就是Student类的属性变量,是Student类所有。而name是外部传来的参数,不是Student类所自带的。故,self.name = name的意思就是把外部传来的参数name的值赋值给Student类自己的属性变量self.name。

4、和普通数相比,在类中定义函数只有一点不同,就是第一参数永远是类的本身实例变量self,并且调用时,不用传递该参数。除此之外,类的方法(函数)和普通函数没啥区别,你既可以用默认参数、可变参数或者关键字参数*args是可变参数,args接收的是一个tuple**kw是关键字参数,kw接收的是一个dict)。

5、既然Student类实例本身就拥有这些数据,那么要访问这些数据,就没必要从外面的函数去访问,而可以直接在Student类的内部定义访问数据的函数(方法),这样,就可以把”数据”封装起来。这些封装数据的函数是和Student类本身是关联起来的,称之为类的方法:

class Student(obiect):    def __init__(self, name, score):        self.name = name        self.score = score    def print_score(self):        print "%s: %s" % (self.name, self.score)

登录后复制

>>>student = Student("Hugh", 99)>>>student.print_scoreHugh: 99

登录后复制

这样一来,我们从外部看Student类,就只需要知道,创建实例需要给出name和score。而如何打印,都是在Student类的内部定义的,这些数据和逻辑被封装起来了,调用很容易,但却不知道内部实现的细节。

如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线,在Python中,实例的变量名如果以开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问,所以,我们把Student类改一改:

class Student(object):    def __init__(self, name, score):        self.__name = name        self.__score = score    def print_score(self):        print "%s: %s" %(self.__name,self.__score)

登录后复制

改完后,对于外部代码来说,没什么变动,但是已经无法从外部访问实例变量.__name和实例变量.__score了:

>>> student = Student('Hugh', 99)>>> student.__nameTraceback (most recent call last):  File "", line 1, in AttributeError: 'Student' object has no attribute '__name'

登录后复制

这样就确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮。

但是如果外部代码要获取name和score怎么办?可以给Student类增加get_name和get_score这样的方法:

class Student(object):    ...    def get_name(self):        return self.__name    def get_score(self):        return self.__score

登录后复制

如果又要允许外部代码修改score怎么办?可以给Student类增加set_score方法:

class Student(object):    ...    def set_score(self, score):        self.__score = score

登录后复制

需要注意的是,在Python中,变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用__name__、__score__这样的变量名。

有些时候,你会看到以一个下划线开头的实例变量名,比如_name,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。

封装的另一个好处是可以随时给Student类增加新的方法,比如:get_grade:

class Student(object):    ...    def get_grade(self):        if self.score >= 90:            return 'A'        elif self.score >= 60:            return 'B'        else:            return 'C'

登录后复制

同样的,get_grade方法可以直接在实例变量上调用,不需要知道内部实现细节:

>>> student.get_grade()'A'

登录后复制

6、self的仔细用法
(1)、self代表类的实例,而非类。

class Test:    def ppr(self):        print(self)        print(self.__class__)t = Test()t.ppr()执行结果:

登录后复制

从上面的例子中可以很明显的看出,self代表的是类的实例。而self.__class__则指向类。
注意:把self换成this,结果也一样,但Python中最好用约定俗成的self。
(2)、self可以不写吗?
在Python解释器的内部,当我们调用t.ppr()时,实际上Python解释成Test.ppr(t),也就是把self替换成了类的实例。

class Test:    def ppr():        print(self)t = Test()t.ppr()

登录后复制

运行结果如下:

Traceback (most recent call last):  File “cl.py”, line 6, in     t.ppr()TypeError: ppr() takes 0 positional arguments but 1 was given

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

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

这里实际上已经部分说明了self在定义时不可以省略。

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

class Test:    def ppr():        print(__class__)Test.ppr()运行结果:

登录后复制

(3)、在继承时,传入的是哪个实例,就是那个传入的实例,而不是指定义了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()

登录后复制

运行结果:

解释:
运行c.cprt()时应该没有理解问题,指的是Child类的实例。
但是在运行c.pprt()时,等同于Child.pprt(c),所以self指的依然是Child类的实例,由于self中没有定义pprt()方法,所以沿着继承树往上找,发现在父类Parent中定义了pprt()方法,所以就会成功调用。

(4)、在描述符类中,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

登录后复制

运行结果如下:

self in Test:
self in Desc:

这里主要的疑问应该在:Desc类中定义的self不是应该是调用它的实例t吗?怎么变成了Desc类的实例了呢?
因为这里调用的是t.x,也就是说是Test类的实例t的属性x,由于实例t中并没有定义属性x,所以找到了类属性x,而该属性是描述符属性,为Desc类的实例而已,所以此处并没有顶用Test的任何方法。

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

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

self in Test: self in Desc:  None 

登录后复制

以上就是Python中的self怎么使用的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2235150.html

(0)
上一篇 2025年2月26日 17:54:13
下一篇 2025年2月26日 17:54:33

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 怎么使用Python中的正则表达式处理html文件

    使用python中的正则表达式处理html文件 finditer方法是一种全匹配方法。已经使用过findall方法的话,该方法将返回由多个匹配字符串组成的列表。对于多个匹配项,finditer会按顺序返回一个迭代器,每个迭代生成一个匹配对象…

    编程技术 2025年2月26日
    000
  • Python类的基本使用方法有哪些

    1、面向对象 类(class):是一种用来描述具有相同属性和方法的对象的集合。 类变量:类变量在整个实例化的对象中是公用的。一般定义在类中且在函数体之外。 方法:类中的函数 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。 …

    编程技术 2025年2月26日
    200
  • Python的五个具有钱途和潜力的岗位

    从2015开始国内就开始慢慢接触Python了,从16年开始Python就已经在国内的热度更高了,目前也可以算的上”全民Python”了。 众所周知小学生的教材里面已经有Python了,国家二级计算机证也需要学习Py…

    2025年2月26日 编程技术
    200
  • Python怎么实现发送声情并茂的邮件内容和附件

    1.准备工作 在开始之前,我们需要准备一些东西。首先,我们需要安装python。python可以从官方网站下载。 其次,我们需要安装smtplib库。这可以通过以下命令在终端中完成: pip install smtplib 登录后复制 2.…

    2025年2月26日 编程技术
    200
  • Python之Pygame的Event事件模块怎么使用

    Pygame的Event事件模块 事件(event)是 pygame 的重要模块之一,它是构建整个游戏程序的核心,比如常用的鼠标点击、键盘敲击、游戏窗口移动、调整窗口大小、触发特定的情节、退出游戏等,这些都可以看做是“事件”。  事件类型 …

    编程技术 2025年2月26日
    200
  • 使用Python进行交易策略和投资组合分析

    我们将在本文中衡量交易策略的表现。并将开发一个简单的动量交易策略,它将使用四种资产类别:债券、股票和房地产。这些资产类别的相关性很低,这使得它们成为了极佳的风险平衡选择。 动量交易策略 这个策略是基于动量的的,因为交易者和投资者早就意识到动…

    2025年2月26日 编程技术
    200
  • python包如何使用

    python 包的模块 函数 类 定义 导入使用详细说明 下面是一个使用 python 包的详细案例,它涉及到模块、函数和类的定义、导入以及使用: 首先,我们创建一个名为 my_package 的目录,作为包的根目录。在其中创建以下文件: …

    编程技术 2025年2月26日
    200
  • Python列表解析和生成器表达式的结构是什么

    列表解析与生成器表达式 生成器表达式是生成容器的一种简洁方式。最常见的是,你会听到列表解析,但也存在集合解析和字典解析。但是,术语上的差异有些重要:如果你实际上是在制作列表,那么它只是一个列表解析。 生成器表达式用括号括起来( ),而列表解…

    编程技术 2025年2月26日
    200
  • Python catplot函数自定义颜色的方法是什么

    一、catplot函数 catplot() 函数是 seaborn 中一个非常有用的函数,它可以绘制分类变量的图形,并可以根据另一个或多个变量进行分组。使用不同的图表类型,catplot() 函数可以创建适当的图表。 默认情况下,catpl…

    2025年2月26日 编程技术
    200
  • Python怎么用Gradio与EasyOCR构建在线识别文本的Web应用

    一、Gradio是什么 gradio是一个开源的 python 库,用于构建机器学习和数据科学演示和 web 应用。 官网:https://www.gradio.app/ Gradio适用于: 演示客户/合作者/用户/学生的机器学习模型。 …

    2025年2月26日 编程技术
    200

发表回复

登录后才能评论