zoukankan      html  css  js  c++  java
  • python——类中的self到底有什么作用

    在python的类中会使用到“self”,本文主要是谈谈类中的self和变量的关系。
    先看示例代码I

    
    

    class Test(object):
      def __init__ (self, val1):
        self.val0 = val1
      def fun1(self):
        print(self.val0)
      def fun2(self, val2):
        print(val2)
      def fun3(self):
        print(self.fun1)
        self.fun1()

    
    

    ins=Test(123)
    ins.new_val=”I’m a new value” # 在实例中添加数据属性

    1、self是什么
    在python的类中self代表实例本身,具体来说,是该实例的内存地址。
    在调用实例的方法时,Python解释器会自己把实例!!变量!!传给类的函数中的self。
    以上述代码I为例,代码I定义了一个类Test,在这个类中,self为参数变量,在类Test实例化得到实例ins时,python解释器自动调用__init__,执行Test.init(ins, 123),该self可接收实例ins的内存地址,从而self代表了实例本身。类似的,如果实例化ins后,执行ins.fun1( ),python解释器会将ins.fun1( )解释成Test.fun1(ins)。可见,self这个变量是无需用户手动传送值的,解释器会自动帮我们给其传递实例。
    需要注意的是,self不是关键字,换言之,可以用其它的合法变量名替换self,但是,规范和标准建议我们一致使用self。

    2、self的使用场景
    在类中,self的使用有下面3个场景:
    1)self为类中的函数的第一个参数,例如在类中,def fun1(self, …)。
    上文说过,“在调用实例的方法时,Python解释器会自己把实例变量传给类的函数中的self”,如果类的函数的第一个参数不是代表实例的self,则调用实例的方法时,该方法没有参数接收解释器自动传入的实例变量,从而程序会产生异常。
    事实上,“和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。除此之外,类的方法和普通函数没有什么区别,所以,你仍然可以用默认参数、可变参数、关键字参数和命名关键字参数”(廖雪峰老师说的)。

    2)在类中,引用实例的属性,示例:self.变量名(如self.val0)。
    引用实例的属性的目的是为实例绑定属性、写入或读取实例的属性。
    例如,在代码I中,在类的函数__init__中,“self.val1 = val1”将属性val0绑定到了实例self(类实例化成ins后,self就代表实例ins了)上,并且将变量val1的值赋给了实例的属性val0。在函数fun1中,print(self.val0),读取了实例self的值val0,并打印出来,当然,在函数中修改属性val0的值也是可以的。

    3)在类中,调用实例的方法,例如,self.fun1();获取实例的方法的地址,例如self.fun1。
    类是抽象的模板,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。既然,self代表实例,则可以“self.函数名”的方式表示实例的方法地址,以“self.函数名()”的方式,调用实例的方法。在类的定义中,以及实例化后对实例方法的调用,都可以这样做。

    3、python的几种变量——按作用域分
    1、全局变量:在模块内、在所有函数外面、在class外面,这就是全局变量。
    2、局部变量:在函数内、在class的方法内(未加self修饰的) ,这就是局部变量
    3、静态变量(也可以说,类属性):在class内的,但不在class的方法内的,这就是静态变量
    4、实例变量(也可以说,实例属性):在class的方法内的,用self修饰的变量,这就是实例变量

    4、self和变量的关系
    综合上述的1、2和3点,可以得到在类中,self和变量的关系了,一言以蔽之,被self修饰的变量是实例变量,不被self修饰的变量不是实例变量。
    实例变量有什么作用,或者说,什么时候应该使用self修饰变量比较好?我的总结如下:
    当我们想将某个变量绑定给实例时,就在类中,使用self修饰该变量。一般来说,类实例化为不同实例后,为了不同实例的某一变量互不干扰,就将该变量绑定给实例。
    具体的使用场景,
    1)若需要在类的不同方法中调用同一变量,且属于同一个类的不同实例的该变量互不影响(即排除类属性),则在类中将该变量绑定给实例。
    2)需要在类实例化得到实例后,修改、或引用实例的某变量,则在类中将该变量绑定给实例。

    a = 1   
    def say():  
        print '调用了全局方法'  
    class people:  
        a = 100  
        def say(self):  
            print '调用了类的方法'  
        def do(self):  
            say()  
            self.say()  
            print 'a = ' , a  
            print 'self.a = ' , self.a  
    p = people()   
    p.do()  
    >>>
    1. 调用了全局方法  
    2. 调用了类的方法  
    3. a =  1  
    4. self.a =  100  
    Python中,类之外可以定义很多全局变量和函数,这是它与java明显的不同。为了解释器准确的找到函数或变量,需要使用self来限定方法变量的区域,这样解释器就能快速知道你调用的是类中的变量还是全局的变量了。 

    5、一点补充
    为实例绑定属性有两种方式
    1)在类的函数__init__中,为实例绑定变量。
    这也是本文讨论的场景。
    根据pep8,所有的加了self的变量,需要确保是在__init__中首次出现,虽然不这样做有些场景下程序也不会出错,但按照规定来吧。
    2)在实例化后,为实例绑定新的属性。例如,实例变量.属性变量=值
    由于Python是动态语言,从而,根据类创建的实例可以任意绑定属性。通过实例变量给实例绑定属性是方法之一,例如代码I中的,ins.newval=”I’m a new value”,为实例绑定了属性newval。不过,这不是本文讨论的关注点

  • 相关阅读:
    poj 2584 T-Shirt Gumbo (二分匹配)
    hdu 1757 A Simple Math Problem (乘法矩阵)
    矩阵之矩阵乘法(转载)
    poj 2239 Selecting Courses (二分匹配)
    hdu 3661 Assignments (贪心)
    hdu 1348 Wall (凸包)
    poj 2060 Taxi Cab Scheme (二分匹配)
    hdu 2202 最大三角形 (凸包)
    hdu 1577 WisKey的眼神 (数学几何)
    poj 1719 Shooting Contest (二分匹配)
  • 原文地址:https://www.cnblogs.com/vincent-sh/p/12780716.html
Copyright © 2011-2022 走看看