python中self,cls

cls主要用在类方法定义,而self则是实例方法。

self, cls 不是关键字,完全可以使用自己写的任意变量代替实现一样的效果。

普通的实例方法,第一个参数需要是self,它表示一个具体的实例本身。
如果用了staticmethod,那么就可以无视这个self,而将这个方法当成一个普通的函数使用。
而对于classmethod,它的第一个参数不是self,是cls,它表示这个类本身。
>>> class A(object):


    def foo1(self):
        print "Hello",self


    @staticmethod
    def foo2():
        print "hello"


    @classmethod
    def foo3(cls):
        print "hello",cls

       
>>> a = A()
>>> a.foo1()          #最常见的调用方式,但与下面的方式相同
Hello <__main__.A object at 0x9f6abec>
>>> A.foo1(a)         #这里传入实例a,相当于普通方法的self
Hello <__main__.A object at 0x9f6abec>
>>> A.foo2()          #这里,由于静态方法没有参数,故可以不传东西
hello
>>> A.foo3()          #这里,由于是类方法,因此,它的第一个参数为类本身。
hello <class '__main__.A'>
>>> A                 #可以看到,直接输入A,与上面那种调用返回同样的信息。
<class '__main__.A'>

---------------------------------------------------------------------------------

类的定义可以动态修改

class MyTest:
    
    myname = 'peter'

    def sayhello(self):
        print "say hello to %s" % self.myname

if __name__ == "__main__":
    MyTest.myname = 'hone'
    MyTest.sayhello = lambda self, name: "I want say hello to %s" % name
    MyTest.saygoodbye = lambda self,name: "I do not want say goodbye to %s" % name
    print MyTest().sayhello(MyTest.myname)
    print MyTest().saygoodbye(MyTest.myname)

这里修改了MyTest类中的变量和函数定义, 实例化的instance有了不同的行为特征。

-------------------------------------------------------------------------------------

1.Python是一门动态语言,任何实体都可以动态地添加或删除属性。
2.一个类定义了一个作用域。
3.类实例也引入了一个作用域,这与相应类定义的作用域不同。
4.在类实例中查找属性的时候,首先在实例自己的作用域中查找,如果没有找到,则再在类定义的作用域中查找。
5.在对类实例属性进行赋值的时候,实际上会在类实例定义的作用域中添加一个属性(如果还不存在的话),并不会影响到相应类中定义的同名属性。

class A:
    cls_i = 0
    cls_j = {}
    
    def __init__(self):
        self.instance_i = 0
        self.instance_j = {}

if __name__ == '__main__':
    a = A()
    print A.__dict__ #{'__init__': , '__module__': '__main__', 'cls_i': 0, 'cls_j': {}, '__doc__': None}
    print a.__dict__ # {'instance_j': {}, 'instance_i': 0}

>>> a.cls_i
0
>>>
a.instance_i
0

在查找cls_i的时候,实例a的作用域中是没有它的,却在A的作用域中找到了它;在查找instance_i的时候,直接可在a的作用域中找到它。


如果我们企图通过实例a来修改cls_i的值,那会怎样呢:
>>> a.cls_i = 1
>>> a.__dict__
{'instance_j': {}, 'cls_i': 1, 'instance_i': 0}
>>> A.__dict__
{'__init__': , '__module__': '__main__', 'cls_i': 0, 'cls_j': {},
'__doc__': None}

我们可以看到,a的作用域中多了一个cls_i属性,其值为1;同时,我们也注意到A作用域中的cls_i属性的值仍然为0;在这里,我们其实是增加了一个实例属性,并没有修改到类属性


如果我们通过实例a操纵cls_j中的数据(注意不是cls_j本身),又会怎么样呢:
>>> a.cls_j['a'] = 'a'
>>> a.__dict__
{'instance_j': {}, 'cls_i': 1, 'instance_i': 0}
>>> A.__dict__
{'__init__': , '__module__': '__main__', 'cls_i': 0, 'cls_j': {'a': 'a'}, '__doc__': None}

我们可以看到a的作用域没有发生什么变化,但是A的作用域发生了一些变化,cls_j中的数据发生了变化。

实例的作用域发生变化,并不会影响到该类的其它实例,但是类的作用域发生变化,则会影响到该类的所有实例,包括在这之前创建的实例.
原文地址:https://www.cnblogs.com/kex1n/p/5983200.html