【Python】self学习笔记

【Python】self详解

在Python中定义类如下:class Student (Object):
通过类来创建实例:student Student()

  • Python中self的含义

      实例Instance本身
      对象(Object),是当前类的实例
      表示是调用的是self对象,即实例的函数
    
  • self存在的意义

     类的代码(函数)中,需要访问当前的实例中的变量和函数
     	对应的变量:Instance.ProperyNam,去读取之前的值和写入新的值
     	调用对应函数(function):Instance.function(),即执行对应的动作
    

Python中规定了函数参数的第一个参数必须是实例对象本身(即self)

由于类起到模板的作用,因此,可以在创建实例的时候,把我们认为必须绑定的属性强制填写进去。这里就用到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解释器会自己把实例变量传进去
  3. 和普通数相比,在类中定义函数只有一点不同,就是第一参数永远是类的本身实例变量self,并且调用时,不用传递该参数。
  4. 既然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类,就只需要知道,创建实例需要给出name和score。而如何打印,都是在Student类的内部定义的,这些数据和逻辑被封装起来了,调用很容易,但却不知道内部实现的细节。

如果要让内部属性不被外部访问,可以把属性的名称前加上**两个下划线**
实例的变量名如果"__"开头,就变成了私有变量(private),只有内部可以访问,外部不能访问
在这里插入图片描述
确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮,但是如果要获取name和score,可以通过使用get_name和get_score的方法,如果允许外部代码修改,则可以增加set_score,具体实现如下:
在这里插入图片描述
在Python中,变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用__name__、__score__这样的变量名。
_name 表示可以访问,但是不要随意访问

补充:
在这里插入图片描述
封装的另一个好处是可以随时给Student类增加新的方法

  • self的详细用法
self代表类的实例,而不是类
class Test:
    def ppr(self):
        print(self)
        print(self.__class__)

t = Test()
t.ppr()
执行结果:
<__main__.Test object at 0x000000000284E080>
<class '__main__.Test'>

self代表的是类的实例。而self.__class__则指向类
把self换成this,结果也一样,但Python中最好用约定俗成的self

self可以省略吗?

在Python解释器的内部,当我们调用t.ppr()时,实际上Python解释成Test.ppr(t),也就是把self替换成了类的实例。
在这里插入图片描述
运行时提醒错误如下:
ppr在定义时没有参数,但是我们运行时强行传了一个参数。
由于上面解释过了t.ppr()等同于Test.ppr(t),所以程序提醒我们多传一个参数t。
这里实际上已经部分说明了self在定义时不可以省略
当然,如果我们的定义和调用时均不传类实例是可以的,这就是类方法
在这里插入图片描述

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

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

举几个例子:

class Person(object):
    def __init__(self, name, lang, website):
        self.name = name
        self.lang = lang
        self.website = website
 
        print('self: ', self)
        print('type of self: ', type(self))
'''
未实例化时,运行程序,构造方法没有运行
'''
 
p = Person('Tim', 'English', 'www.universal.com')   
 
'''实例化后运行的结果
self:  <__main__.Person object at 0x00000000021EAF98>
type of self:  <class '__main__.Person'>
'''
class Person(object):
    def __init__(self, newPersonName):
        # self.name = newPersonName
        '''
        如果此处不写成self.name
        那么此处的name,只是__init__函数中的局部临时变量name而已
        和全局中的name,没有半毛钱关系
        '''
        name = newPersonName
        '''
        此处只是为了代码演示,而使用了局部变量name,
        不过需要注意的是,此处很明显,由于接下来的代码也没有利用到此处的局部变量name
        则就导致了,此处的name变量,实际上被浪费了,根本没有利用到
        '''
    def sayYourName(self):
        '''
        此处由于找不到实例中的name变量,所以会报错:
        AttributeError: Person instance has no attribute 'name'
        '''
        print('My name is %s' %self.name)
 
def selfAndInitDemo():
    personInstance = Person('Tim')
    personInstance.sayYourName()
 
if __name__ == '__main__':
    selfAndInitDemo()
name = 'whole global name'
'''
注:此处全局的变量名,写成name,只是为了演示而用
实际上,好的编程风格,应该写成gName之类的名字,
以表示该变量是Global的变量
'''
 
class Person(object):
    def __init__(self, newPersonName):
        self.name = newPersonName
        '''
        此处正确的,通过访问self.name的形式,实现了:
            1.给实例中,增加了name变量
            2.并且给name赋了初值,为newPersionName
        '''
    def sayYourName(self):
        '''
        此处由于开始正确的初始化了self对象,使得其中有了name变量,
        所以此处可以正确访问了name值了
        '''
        print('My name is %s' %self.name)
 
def selfAndInitDemo():
    personInstance = Person('Tim')
    personInstance.sayYourName()
 
if __name__ == '__main__':
    selfAndInitDemo()
 
 
'''My name is Tim'''

参考:
参考一
参考二

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值