Home >  > Python 类self 详解

Python 类self 详解

1

Python 中的self是学习类的一个难点,很多初学者学到Python self的时候,都会出现难以理解的情况,下面,蜗牛博客就为您进行讲解一下Python中的self。

Updated on Nov-02-2018:

一、首先要明确几个概念:

1. self代表类的实例,而非类。
例:

1class Person:
2   def pri(self):
3       print(self)
4a = Person()
5a.pri()
6print(id(a))

运行结果:

1<__main__.Person object at0x04B37A90>
278871184

将0x04B37A90转换成十进制为78871184,与self的id相同,说明在这里self代表的是实例a的id地址。

下面这个例子其实更好:
首先定义一个函数:

1class TestSelf:
2    def self_id(self):
3        return self # 返回self自身
1t1 = TestSelf() # 实例化为一个对象t1
2print(t1) # 打印t1对象自身,
3print(t1.self_id()) # 打印t1对象的self_id方法的返回值
4# 输出
5# <__main__.TestSelf object at 0x1055afbe0>
6# <__main__.TestSelf object at 0x1055afbe0>
7print(t1 is t1.self_id()) # 使用is判断他们的指向是否一致
8# 输出
9# True

那么我们就可以看到有这样的写法;

1class MainEngine:
2    """
3 
4    """
5 
6    def add_engine(self, engine_class: Any):
7        """
8        Add function engine.
9        """
10        engine = engine_class(self, self.event_engine)
11        self.engines[engine.engine_name] = engine

其中的engine = engine_class(self, self.event_engine)相当于engine = engine_class(mainEngine(), self.event_engine)

2. self可以不写吗
(1)编写类中的函数时,不写self会报错。
例:如下面这个最简单的类可以正常运行的,如果删除def prt(self)中的self,就会报“TypeError: enten88() takes no arguments (1 given)”的错误。

1class Test(object):
2    def prt():
3        print("this is test")
4 
5b = Test()
6b.prt()

这其实与class中函数调用的方式有关,在给出一个实例以后,我们调用类中的具体方法(即函数)时,默认传入了self参数(即实例地址),如上面的实例,我们在定义函数时没有给他形参,那么调用时自动传入的第一个参数self无处容纳,即参数多余,报错。

(2)没有self可以运行
下面的代码其实是可以运行的。因为这里没有调用实例,没有self传入,那么也就不向pri传递参数了(特例)。

1class Person:
2    def pri():
3        print('test successfully')
4 
5Person.pri()

上面是python3的版本,但是在python2.x下面

1class Person(object):
2    def pri():
3        print 'test successfully'
4 
5Person.pri()

会报错:

Traceback (most recent call last):
File "test.py", line 59, in
Person.pri()
TypeError: unbound method pri() must be called with Person instance as first arg
ument (got nothing instead)

3. 在继承时,使用的数据是传入实例的数据,而非定义self的父类的数据。
例:

1class Parent:
2    def pprt(self):
3        print(self)
4  
5class Child(Parent):
6    def cprt(self):
7        print(self)
8c = Child()
9c.cprt()
10c.pprt()
11p = Parent()
12p.pprt()

运行结果如下

1<__main__.Child object at 0x0000000002A47080>
2<__main__.Child object at 0x0000000002A47080>
3<__main__.Parent object at 0x0000000002A47240>

运行c.cprt()时应该没有理解问题,指的是Child类的实例。

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

更多知识可以看这里:http://python.jobbole.com/81921/

二、self与变量

1class Test(object):
2    quip = "This is a test!"
3 
4    def prt(self):
5        print quip
6 
7b = Test()
8b.prt()

会报错:

这时,只需要将

改成:

或者

就可以正常显示结果了。

三、self必须是self吗?

我们先看一个标准类的写法:

1class Song():
2    def __init__(self,lyrics):
3        self.lyric = lyrics 
4 
5    def sing_me_a_song(self):
6        for line in self.lyric:
7            print line
8 
9happy_baby = Song(['happy birthday to you',
10                   'I do not want to get sued',
11                   'So i will stop right there'])
12 
13bulls_on_parade = Song(['They rally around the family',
14                        'with pockets full of shells'])
15 
16happy_baby.sing_me_a_song()
17bulls_on_parade.sing_me_a_song()

运行结果如下:
Snap18116

说明:在代码:

1self.lyric = lyrics

中,等号左边的那个lyric是实例的属性,后面那个lyric是方法__init__的参数,两个是不同的

然后,我将将代码改成如下的形式:

1class Song():
2    def __init__(me,lyrics):
3        me.a = lyrics
4 
5 
6    def sing_me_a_song(me):
7        for line in me.a:
8            print line
9 
10happy_baby = Song(['happy birthday to you',
11                   'I do not want to get sued',
12                   'So i will stop right there'])
13 
14bulls_on_parade = Song(['They rally around the family',
15                        'with pockets full of shells'])
16 
17happy_baby.sing_me_a_song()
18bulls_on_parade.sing_me_a_song()

程序照样能运行,且运行的结果一模一样。

那么,我们可不可以不用这个self(或者其他名称),比如将代码中的

1self.lyric = lyrics

直接改成呢?

您可以自己试一试,答案是不行的,这样等于定义了一个全局的变量。

所以我们可以得出如下的结论:
Self是必须的,但是名称不一定必须是self,你可以改成做任意的其他名字,不过在一个类中,定义所有的函数时都必须统一用这一个名字,比如上面的例子中,要么统一用self,要么统一用me,不能在一个类中,又有self,又有me。

暧昧帖

本文暂无标签
Comment (1)
Trackback (0)
  1. vv Google Chrome 110.0.0.0unknow 沙发 2023/02/23 20:58

    engine = engine_class(self, self.event_engine)
    engine_class是Any类型,engine_class()又是什么意思?可以详细讲一下吗?我对这一块不是很懂,谢谢啦!

  • 还没有Trackback

发表评论 点击这里取消回复。

*

*